PHP Toolkit

Blueprints

Declarative WordPress site provisioning. Write a JSON description of plugins, options, and content; let the runner execute it.

composer require wp-php-toolkit/blueprints

A WordPress environment is more than a database dump. It can require a specific core version, plugins, themes, site options, uploaded files, content, and setup steps. Rebuilding that by hand makes demos, tests, bug reports, workshops, and CI fixtures drift over time.

The Blueprints component treats site setup as data. A blueprint JSON document describes the desired steps, and the runner applies them to either a new WordPress install or an existing one. The validator exists because user-authored JSON needs clear, path-specific errors rather than generic schema failures.

RunnerConfiguration separates the web root from the WordPress core directory, since real hosts often put them in different places. Both paths are explicit on the runner, never inferred.

Blueprints can create a new WordPress install (download core, set up the database, apply steps) or apply to an existing site. Creating a fresh install needs filesystem access this in-browser runtime doesn't have, so the runnable snippets focus on APPLY_TO_EXISTING_SITE.

Configure a runner for an existing site

RunnerConfiguration is a fluent builder. The minimum: target site root, target site URL, execution mode.

<?php
require '/wordpress/wp-content/php-toolkit/vendor/autoload.php';

use WordPress\Blueprints\Runner;
use WordPress\Blueprints\RunnerConfiguration;

$config = ( new RunnerConfiguration() )
	->set_execution_mode( Runner::EXECUTION_MODE_APPLY_TO_EXISTING_SITE )
	->set_target_site_root( '/wordpress' )
	->set_target_site_url( 'http://playground.test/' );

echo "mode: " . $config->get_execution_mode() . "\n";
echo "root: " . $config->get_target_site_root() . "\n";
echo "url:  " . $config->get_target_site_url() . "\n";

Generate blueprint JSON from PHP

CI jobs and tests stay clearer when PHP builds the blueprint from data instead of hand-writing JSON. Keep the structure plain: version, then a list of step arrays.

<?php
require '/wordpress/wp-content/php-toolkit/vendor/autoload.php';

$site_name = 'Demo Site';
$plugins   = array( 'gutenberg', 'classic-editor' );

$blueprint = array(
	'version' => 2,
	'steps'   => array(
		array(
			'step'    => 'setSiteOptions',
			'options' => array(
				'blogname'              => $site_name,
				'permalink_structure'   => '/%postname%/',
				'show_on_front'         => 'page',
			),
		),
	),
);

foreach ( $plugins as $slug ) {
	$blueprint['steps'][] = array(
		'step'       => 'installPlugin',
		'pluginData' => "https://downloads.wordpress.org/plugin/{$slug}.zip",
	);
	$blueprint['steps'][] = array(
		'step'   => 'activatePlugin',
		'plugin' => "{$slug}/{$slug}.php",
	);
}

echo json_encode( $blueprint, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . "\n";

Validate before running

The schema validator returns a human-readable ValidationError instead of a generic "does not match schema" failure. Use it before handing user-authored JSON to a runner.

<?php
require '/wordpress/wp-content/php-toolkit/vendor/autoload.php';

use WordPress\Blueprints\Validator\HumanFriendlySchemaValidator;

$schema = array(
	'type'       => 'object',
	'required'   => array( 'version', 'steps' ),
	'properties' => array(
		'version' => array( 'type' => 'integer' ),
		'steps'   => array(
			'type'  => 'array',
			'items' => array(
				'type'       => 'object',
				'required'   => array( 'step' ),
				'properties' => array(
					'step' => array( 'type' => 'string' ),
				),
			),
		),
	),
);

$blueprint = array(
	'version' => 2,
	'steps'   => array(
		array( 'pluginData' => 'https://downloads.wordpress.org/plugin/gutenberg.zip' ),
	),
);

$error = ( new HumanFriendlySchemaValidator( $schema ) )->validate( $blueprint );
if ( null === $error ) {
	echo "valid\n";
} else {
	echo $error->get_pretty_path() . ": " . $error->message . "\n";
}

The Blueprint JSON shape

A blueprint is a JSON document with a version field and a steps array. Each step has a "step" discriminator and step-specific fields. This is the same shape used by WordPress Playground.

{
  "version": 2,
  "steps": [
    { "step": "setSiteOptions",
      "options": {
        "blogname": "Demo Site",
        "permalink_structure": "/%postname%/"
      } },
    { "step": "installPlugin",
      "pluginData": "https://downloads.wordpress.org/plugin/gutenberg.zip" },
    { "step": "activatePlugin",
      "plugin": "gutenberg/gutenberg.php" }
  ]
}

See also