Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions components/Blueprints/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use WordPress\Blueprints\Steps\ActivateThemeStep;
use WordPress\Blueprints\Steps\CpStep;
use WordPress\Blueprints\Steps\DefineConstantsStep;
use WordPress\Blueprints\Steps\EnableMultisiteStep;
use WordPress\Blueprints\Steps\Exception;
use WordPress\Blueprints\Steps\ImportContentStep;
use WordPress\Blueprints\Steps\ImportMediaStep;
Expand Down Expand Up @@ -673,6 +674,8 @@ private function createStepObject( string $stepType, array $data ) {
return new CpStep( $data['fromPath'], $data['toPath'] );
case 'defineConstants':
return new DefineConstantsStep( $data['constants'] );
case 'enableMultisite':
return new EnableMultisiteStep( $data['wpCliPath'] ?? null );
case 'importContent':
/**
* Flatten the content declaration from
Expand Down
45 changes: 45 additions & 0 deletions components/Blueprints/Steps/EnableMultisiteStep.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace WordPress\Blueprints\Steps;

use WordPress\Blueprints\Progress\Tracker;
use WordPress\Blueprints\Runtime;

/**
* Represents the 'enableMultisite' step.
*/
class EnableMultisiteStep implements StepInterface {
/**
* Optional path to the WP-CLI executable.
* @var string|null
*/
public $wpCliPath;

/**
* @param string|null $wpCliPath Optional path to WP-CLI executable.
*/
public function __construct( ?string $wpCliPath = null ) {
$this->wpCliPath = $wpCliPath;
}

public function run( Runtime $runtime, Tracker $tracker ) {
$tracker->setCaption( 'Enabling WordPress multisite' );

$wp_cli_path = $this->wpCliPath ?? $runtime->getWpCliPath();
$site_url = $runtime->getConfiguration()->getTargetSiteUrl();

// Convert existing WordPress installation to multisite
$process = $runtime->startShellCommand( [
'php',
$wp_cli_path,
'core',
'multisite-convert',
// For Docker compatibility. If we got this far, Blueprint runner was already
// allowed to run as root.
'--allow-root',
'--url=' . $site_url,
'--title=Multisite Network',
] );
$process->mustRun();
}
}
67 changes: 67 additions & 0 deletions components/Blueprints/Tests/Unit/Steps/EnableMultisiteStepTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace WordPress\Blueprints\Tests\Unit\Steps;

use WordPress\Blueprints\Progress\Tracker;
use WordPress\Blueprints\Steps\EnableMultisiteStep;

class EnableMultisiteStepTest extends StepTestCase {
/**
* Test enabling multisite
*/
public function testEnableMultisite() {
$step = new EnableMultisiteStep();
$tracker = new Tracker();
$step->run( $this->runtime, $tracker );

// Verify multisite is enabled by checking for multisite constants in wp-config.php
$this->assertMultisiteEnabled();
}

/**
* Test enabling multisite with custom WP-CLI path
*/
public function testEnableMultisiteWithCustomWpCliPath() {
$customWpCliPath = $this->runtime->getWpCliPath(); // Use the same path for testing
$step = new EnableMultisiteStep( $customWpCliPath );
$tracker = new Tracker();
$step->run( $this->runtime, $tracker );

// Verify multisite is enabled
$this->assertMultisiteEnabled();
}

/**
* Helper to verify multisite is enabled
*/
private function assertMultisiteEnabled() {
$result = $this->runtime->evalPhpCodeInSubProcess(
<<<'PHP'
<?php
require_once getenv('DOCROOT') . '/wp-load.php';

// Check if multisite constants are defined
$is_multisite = defined('MULTISITE') && MULTISITE;
$is_subdomain = defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL;

append_output( json_encode([
'multisite' => $is_multisite,
'subdomain_install' => $is_subdomain,
'multisite_function' => function_exists('is_multisite') && is_multisite()
]) );
PHP
)->outputFileContent;

$multisite_status = json_decode( $result, true );

$this->assertTrue(
$multisite_status['multisite'],
'WordPress multisite should be enabled (MULTISITE constant should be true)'
);

$this->assertTrue(
$multisite_status['multisite_function'],
'WordPress is_multisite() function should return true'
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace WordPress\Blueprints\Tests\Unit\Versions\Version1;

use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use WordPress\Blueprints\Versions\Version1\V1ToV2Transpiler;

class V1ToV2TranspilerTest extends TestCase {
private $transpiler;

protected function setUp(): void {
$this->transpiler = new V1ToV2Transpiler( new NullLogger() );
}

/**
* Test converting enableMultisite step from v1 to v2
*/
public function testConvertEnableMultisiteStep() {
$v1Blueprint = [
'steps' => [
[
'step' => 'enableMultisite'
]
]
];

$v2Blueprint = $this->transpiler->upgrade( $v1Blueprint );

$this->assertArrayHasKey( 'additionalStepsAfterExecution', $v2Blueprint );
$this->assertCount( 1, $v2Blueprint['additionalStepsAfterExecution'] );

$step = $v2Blueprint['additionalStepsAfterExecution'][0];
$this->assertEquals( 'enableMultisite', $step['step'] );
$this->assertArrayNotHasKey( 'wpCliPath', $step );
}

/**
* Test converting enableMultisite step with custom wpCliPath from v1 to v2
*/
public function testConvertEnableMultisiteStepWithCustomWpCliPath() {
$v1Blueprint = [
'steps' => [
[
'step' => 'enableMultisite',
'wpCliPath' => '/custom/path/to/wp-cli.phar'
]
]
];

$v2Blueprint = $this->transpiler->upgrade( $v1Blueprint );

$this->assertArrayHasKey( 'additionalStepsAfterExecution', $v2Blueprint );
$this->assertCount( 1, $v2Blueprint['additionalStepsAfterExecution'] );

$step = $v2Blueprint['additionalStepsAfterExecution'][0];
$this->assertEquals( 'enableMultisite', $step['step'] );
$this->assertEquals( '/custom/path/to/wp-cli.phar', $step['wpCliPath'] );
}

/**
* Test that v2 blueprint doesn't warn about enableMultisite anymore
*/
public function testNoWarningForEnableMultisite() {
$v1Blueprint = [
'steps' => [
[
'step' => 'enableMultisite'
]
]
];

// This should not throw any warnings or exceptions
$v2Blueprint = $this->transpiler->upgrade( $v1Blueprint );

// Verify the step was actually converted and not ignored
$this->assertNotEmpty( $v2Blueprint['additionalStepsAfterExecution'] );
$this->assertEquals( 'enableMultisite', $v2Blueprint['additionalStepsAfterExecution'][0]['step'] );
}
}
10 changes: 7 additions & 3 deletions components/Blueprints/Versions/Version1/V1ToV2Transpiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,13 @@ public function upgrade( array $validated_v1_blueprint ): array {
$this->logger->warning( 'The `defineSiteUrl` step is not supported by the Blueprint v2 schema. Use the runner configuration to set the site URL instead.' );
break;
case 'enableMultisite':
// @TODO: Support this step in v3. Multisites will require a separate schema
// that defines what's related to which site.
$this->logger->warning( 'The `enableMultisite` step is not supported by the Blueprint v2 schema and will be ignored.' );
$v2step = [
'step' => 'enableMultisite',
];
if ( isset( $v1step['wpCliPath'] ) ) {
$v2step['wpCliPath'] = $v1step['wpCliPath'];
}
$v2steps[] = $v2step;
break;
case 'importWordPressFiles':
if ( isset( $v1step['progress'] ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,14 @@ type DefineConstantsStep = {
constants: WordPressConstants;
};

type EnableMultisiteStep = {
step: 'enableMultisite';
/**
* Optional path to the WP-CLI executable.
*/
wpCliPath?: string;
};

type ImportContentStep = {
step: 'importContent';
content: ContentDefinition[];
Expand Down Expand Up @@ -1572,6 +1580,7 @@ type Step =
| ActivateThemeStep
| CpStep
| DefineConstantsStep
| EnableMultisiteStep
| ImportContentStep
| ImportMediaStep
| ImportThemeStarterContentStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,4 @@ described below. On a successful merge, the runner **MUST** execute the merged B

## Areas intentionally not covered by this proposal

- Multisite configuration – it may require a separate schema and is left for a future iteration of the Blueprint
standard.
- Content import format – it is a separate, nuanced topic that warrants a dedicated proposal.
Binary file not shown.
Loading
Loading