Skip to content
Open
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
60 changes: 53 additions & 7 deletions components/Blueprints/SiteResolver/class-existingsiteresolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,26 @@ public static function resolve( Runtime $runtime, Tracker $progress, ?VersionCon

// 1. Verify it's a valid WordPress installation.
$progress['verify_installation']->setCaption( 'Verifying WordPress installation' );

// Auto-detect the WordPress core directory. Some hosting setups place
// the WordPress core files (wp-load.php, wp-admin, wp-includes) in a
// subdirectory while wp-content stays in the web root.
if ( ! $target_fs->exists( 'wp-load.php' ) ) {
throw new BlueprintExecutionException(
'The target site does not appear to be a valid WordPress installation (wp-load.php not found)'
);
$detected_core_dir = self::detect_wordpress_core_dir( $config->get_target_site_root() );
if ( null !== $detected_core_dir ) {
$config->set_wordpress_core_dir( $detected_core_dir );
} else {
throw new BlueprintExecutionException(
'The target site does not appear to be a valid WordPress installation (wp-load.php not found)'
);
}
}

// Additional check to ensure we can actually load WordPress.
try {
$result = $runtime->eval_php_code_in_subprocess(
'<?php
require_once(getenv("DOCROOT") . "/wp-load.php");
require_once(getenv("WP_CORE_DIR") . "/wp-load.php");
$is_installed = function_exists("is_blog_installed") && is_blog_installed() ? "true" : "false";
append_output("WordPress is installed: " . $is_installed);
'
Expand All @@ -61,7 +70,7 @@ public static function resolve( Runtime $runtime, Tracker $progress, ?VersionCon
trim(
$runtime->eval_php_code_in_subprocess(
'<?php
require_once(getenv("DOCROOT") . "/wp-includes/version.php");
require_once(getenv("WP_CORE_DIR") . "/wp-includes/version.php");
append_output( $wp_version );
'
)->output_file_content
Expand Down Expand Up @@ -92,7 +101,7 @@ public static function resolve( Runtime $runtime, Tracker $progress, ?VersionCon
if ( 'sqlite' === $required_engine ) {
$sqlite_active = $runtime->eval_php_code_in_subprocess(
'<?php
require_once(getenv("DOCROOT") . "/wp-load.php");
require_once(getenv("WP_CORE_DIR") . "/wp-load.php");

// Check if SQLite integration is active
$sqlite_plugin = WP_CONTENT_DIR . "/plugins/sqlite-database-integration/load.php";
Expand All @@ -113,7 +122,7 @@ public static function resolve( Runtime $runtime, Tracker $progress, ?VersionCon
// For MySQL, verify it's not using SQLite.
$using_mysql = $runtime->eval_php_code_in_subprocess(
'<?php
require_once(getenv("DOCROOT") . "/wp-load.php");
require_once(getenv("WP_CORE_DIR") . "/wp-load.php");

// Check if SQLite integration is NOT active
$active_plugins = get_option("active_plugins");
Expand All @@ -139,4 +148,41 @@ public static function resolve( Runtime $runtime, Tracker $progress, ?VersionCon
$progress['verify_database']->finish();
$progress->finish();
}

/**
* Scans the web root for a WordPress core directory. Some hosting
* setups place the core files in a subdirectory while wp-content/
* stays in the web root.
*
* @param string $web_root Absolute path to the web root.
*
* @return string|null Absolute path to the WordPress core directory, or
* null when wp-load.php cannot be found anywhere.
*/
public static function detect_wordpress_core_dir( string $web_root ): ?string {
// Standard layout: wp-load.php is in the web root itself.
if ( file_exists( $web_root . '/wp-load.php' ) ) {
return $web_root;
}

// Scan immediate subdirectories for wp-load.php. This covers the
// Check immediate subdirectories for any single-level split layout.
$entries = @scandir( $web_root );
if ( false === $entries ) {
return null;
}

foreach ( $entries as $entry ) {
if ( '.' === $entry || '..' === $entry ) {
continue;
}

$candidate = $web_root . '/' . $entry;
if ( is_dir( $candidate ) && file_exists( $candidate . '/wp-load.php' ) ) {
return $candidate;
}
}

return null;
}
}
5 changes: 3 additions & 2 deletions components/Blueprints/SiteResolver/class-newsiteresolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private static function is_wordpress_installed( Runtime $runtime, Tracker $progr
$install_check = $runtime->eval_php_code_in_subprocess(
<<<'PHP'
<?php
$wp_load = getenv('DOCROOT') . '/wp-load.php';
$wp_load = getenv('WP_CORE_DIR') . '/wp-load.php';
if (!file_exists($wp_load)) {
append_output('0');
exit;
Expand All @@ -164,7 +164,8 @@ private static function is_wordpress_installed( Runtime $runtime, Tracker $progr
PHP
,
array(
'DOCROOT' => $runtime->get_configuration()->get_target_site_root(),
'DOCROOT' => $runtime->get_configuration()->get_target_site_root(),
'WP_CORE_DIR' => $runtime->get_configuration()->get_wordpress_core_dir(),
),
null,
5
Expand Down
4 changes: 2 additions & 2 deletions components/Blueprints/Steps/class-activatepluginstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class ActivatePluginStep implements StepInterface {
<?php

define( 'WP_ADMIN', true );
require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/plugin.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/plugin.php';

// Set current user to admin
set_current_user( get_users( array( 'role' => 'Administrator' ) )[0] );
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/class-activatethemestep.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ActivateThemeStep implements StepInterface {
<?php

define( 'WP_ADMIN', true );
require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';

// Set current user to admin
set_current_user( get_users( array( 'role' => 'Administrator' ) )[0] );
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/class-defineconstantsstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ function find_first_token_index( $tokens, $type, $search = null ) {
return null;
}

$wp_config_path = getenv( "DOCROOT" ) . "/wp-config.php";
$wp_config_path = getenv( "WP_CORE_DIR" ) . "/wp-config.php";

if ( ! file_exists( $wp_config_path ) ) {
error_log( "Blueprint Error: wp-config.php file not found at " . $wp_config_path );
Expand Down
4 changes: 2 additions & 2 deletions components/Blueprints/Steps/class-enablemultisitestep.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public function run( Runtime $runtime, Tracker $tracker ) {
* See: https://github.com/wp-cli/core-command/blob/f157fb37dae1d13fe7318452f932917161e83e53/src/Core_Command.php#L505
*/

require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/upgrade.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/upgrade.php';

// need to register the multisite tables manually for some reason
foreach ( $wpdb->tables( 'ms_global' ) as $table => $prefixed_table ) {
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/class-importcontentstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private function importPosts( Runtime $runtime, $post ): void {
$runtime->eval_php_code_in_subprocess(
<<<'PHP'
<?php
require_once getenv('DOCROOT') . '/wp-load.php';
require_once getenv('WP_CORE_DIR') . '/wp-load.php';
foreach (json_decode(getenv('POSTS'), true) as $post) {
$result = wp_insert_post(wp_slash($post));
if (is_wp_error($result)) {
Expand Down
6 changes: 3 additions & 3 deletions components/Blueprints/Steps/class-importmediastep.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function run( Runtime $runtime, Tracker $progress ) {
$fs = $runtime->get_target_filesystem();
$wp_upload_dir = $runtime->eval_php_code_in_subprocess(
'<?php
require_once(getenv("DOCROOT") . "/wp-load.php");
require_once(getenv("WP_CORE_DIR") . "/wp-load.php");
$upload_dir = wp_upload_dir();
append_output( json_encode($upload_dir) );
'
Expand Down Expand Up @@ -130,8 +130,8 @@ function ( $media ) {
$attachment_id = $runtime->eval_php_code_in_subprocess(
<<<'CODE'
<?php
require_once(getenv("DOCROOT") . "/wp-load.php");
require_once(getenv("DOCROOT") . "/wp-admin/includes/image.php");
require_once(getenv("WP_CORE_DIR") . "/wp-load.php");
require_once(getenv("WP_CORE_DIR") . "/wp-admin/includes/image.php");

$file_path = getenv("MEDIA_FILE_PATH");
$attachment_meta = json_decode(getenv("ATTACHMENT_META"), true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function importThemeStarterContent_plugins_loaded() {
'accepted_args' => 0,
);

require getenv( "DOCROOT" ) . '/wp-load.php';
require getenv( "WP_CORE_DIR" ) . '/wp-load.php';

// Return early if there's no starter content.
if ( ! get_theme_starter_content() ) {
Expand Down
14 changes: 7 additions & 7 deletions components/Blueprints/Steps/class-installpluginstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ function ( $temp_dir ) use ( $runtime, $tracker, $plugin_data ) {
<<<'PHP'
<?php

require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';

define( 'WP_ADMIN', true );

// Define a dummy skin for the upgrader.
if ( ! class_exists( '\WP_Upgrader_Skin', false ) ) {
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/class-wp-upgrader.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/class-wp-upgrader.php';

class Blueprint_WP_Upgrader_Skin extends WP_Upgrader_Skin {
public $destination;
Expand Down Expand Up @@ -186,11 +186,11 @@ public function after( $title = '' ) {
}
}

require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/plugin.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/file.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/plugin-install.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/class-wp-upgrader.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/plugin.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/file.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/plugin-install.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/class-wp-upgrader.php';

// Ensure filesystem access is properly set up
WP_Filesystem();
Expand Down
12 changes: 6 additions & 6 deletions components/Blueprints/Steps/class-installthemestep.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,16 @@ function ( $temp_dir ) use ( $runtime, $tracker ) {
<<<'PHP'
<?php

require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';

define( 'WP_ADMIN', true );

// Load required WordPress files
require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/file.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/theme.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/class-wp-upgrader.php';
require_once getenv( 'DOCROOT' ) . '/wp-admin/includes/misc.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/file.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/theme.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/class-wp-upgrader.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-admin/includes/misc.php';

// Define show_message function if it doesn't exist (fallback)
if ( ! function_exists( 'show_message' ) ) {
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/class-runsqlstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function run( Runtime $runtime, Tracker $tracker ) {
$runtime->eval_php_code_in_subprocess(
<<<'CODE'
<?php
require_once getenv("DOCROOT") . '/wp-load.php';
require_once getenv("WP_CORE_DIR") . '/wp-load.php';
$handle = STDIN;
$buffer = '';
global $wpdb;
Expand Down
10 changes: 5 additions & 5 deletions components/Blueprints/Steps/class-setsitelanguagestep.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function run( Runtime $runtime, Tracker $progress ) {
$wp_version = trim(
$runtime->eval_php_code_in_subprocess(
'<?php
require getenv("DOCROOT") . "/wp-includes/version.php";
require getenv("WP_CORE_DIR") . "/wp-includes/version.php";
append_output( $wp_version );
'
)->output_file_content
Expand All @@ -67,8 +67,8 @@ public function run( Runtime $runtime, Tracker $progress ) {
$plugins_data = json_decode(
$runtime->eval_php_code_in_subprocess(
"<?php
require_once(getenv('DOCROOT') . '/wp-load.php');
require_once(getenv('DOCROOT') . '/wp-admin/includes/plugin.php');
require_once(getenv('WP_CORE_DIR') . '/wp-load.php');
require_once(getenv('WP_CORE_DIR') . '/wp-admin/includes/plugin.php');
append_output(
json_encode(
array_values(
Expand Down Expand Up @@ -97,8 +97,8 @@ function(\$plugin) {
$themes_data = json_decode(
$runtime->eval_php_code_in_subprocess(
"<?php
require_once(getenv('DOCROOT') . '/wp-load.php');
require_once(getenv('DOCROOT') . '/wp-admin/includes/theme.php');
require_once(getenv('WP_CORE_DIR') . '/wp-load.php');
require_once(getenv('WP_CORE_DIR') . '/wp-admin/includes/theme.php');
append_output(
json_encode(
array_values(
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/class-setsiteoptionsstep.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function run( Runtime $runtime, Tracker $tracker ) {
$tracker->setCaption( 'Setting site options' );
$runtime->eval_php_code_in_subprocess(
'<?php
require getenv(\'DOCROOT\'). \'/wp-load.php\';
require getenv(\'WP_CORE_DIR\'). \'/wp-load.php\';
$site_options = getenv("OPTIONS") ? json_decode(getenv("OPTIONS"), true) : [];
foreach($site_options as $name => $value) {
update_option($name, $value);
Expand Down
2 changes: 1 addition & 1 deletion components/Blueprints/Steps/scripts/import-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

use function WordPress\Filesystem\wp_join_unix_paths;

require_once getenv( 'DOCROOT' ) . '/wp-load.php';
require_once getenv( 'WP_CORE_DIR' ) . '/wp-load.php';
require_once getenv( 'DOCROOT' ) . '/php-toolkit.phar';

// Progress reporting interfaces and implementations.
Expand Down
45 changes: 45 additions & 0 deletions components/Blueprints/Tests/Unit/RunnerConfigurationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace WordPress\Blueprints\Tests\Unit;

use PHPUnit\Framework\TestCase;
use WordPress\Blueprints\RunnerConfiguration;

class RunnerConfigurationTest extends TestCase {

/**
* When no WordPress core dir is set, it defaults to the target site root.
*/
public function test_wordpress_core_dir_defaults_to_site_root() {
$config = new RunnerConfiguration();
$config->set_target_site_root( '/srv/htdocs' );

$this->assertSame( '/srv/htdocs', $config->get_wordpress_core_dir() );
}

/**
* When a WordPress core dir is explicitly set, it takes precedence
* over the target site root.
*/
public function test_wordpress_core_dir_can_be_set_independently() {
$config = new RunnerConfiguration();
$config->set_target_site_root( '/srv/htdocs' );
$config->set_wordpress_core_dir( '/srv/htdocs/wp' );

$this->assertSame( '/srv/htdocs', $config->get_target_site_root() );
$this->assertSame( '/srv/htdocs/wp', $config->get_wordpress_core_dir() );
}

/**
* Setting WordPress core dir to null resets to the default behavior
* (falling back to the site root).
*/
public function test_wordpress_core_dir_reset_to_null_falls_back_to_site_root() {
$config = new RunnerConfiguration();
$config->set_target_site_root( '/srv/htdocs' );
$config->set_wordpress_core_dir( '/srv/htdocs/wp' );
$config->set_wordpress_core_dir( null );

$this->assertSame( '/srv/htdocs', $config->get_wordpress_core_dir() );
}
}
Loading
Loading