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
72 changes: 72 additions & 0 deletions features/core-install.feature
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,78 @@ Feature: Install WordPress core
"""
And the return code should be 0

Scenario: Verify correct siteurl and home when URL has no path
Given an empty directory
And WP files
And wp-config.php
And a database

When I run `wp core install --url=example.com --title=Test --admin_user=wpcli --admin_email=wpcli@example.org --admin_password=password --skip-email`
Then STDOUT should contain:
"""
Success: WordPress installed successfully.
"""

When I run `wp option get home`
Then STDOUT should be:
"""
http://example.com
"""

When I run `wp option get siteurl`
Then STDOUT should be:
"""
http://example.com
"""

Scenario: Verify correct siteurl and home when URL has a path
Given an empty directory
And WP files
And wp-config.php
And a database

When I run `wp core install --url=example.com/subdir --title=Test --admin_user=wpcli --admin_email=wpcli@example.org --admin_password=password --skip-email`
Then STDOUT should contain:
"""
Success: WordPress installed successfully.
"""

When I run `wp option get home`
Then STDOUT should be:
"""
http://example.com/subdir
"""

When I run `wp option get siteurl`
Then STDOUT should be:
"""
http://example.com/subdir
"""

Scenario: Install ensures correct siteurl and home regardless of PHP_SELF
Given an empty directory
And WP files
And wp-config.php
And a database

When I run `wp core install --url=https://example.com --title=Test --admin_user=wpcli --admin_email=wpcli@example.org --admin_password=password --skip-email`
Then STDOUT should contain:
"""
Success: WordPress installed successfully.
"""

When I run `wp option get home`
Then STDOUT should be:
"""
https://example.com
"""

When I run `wp option get siteurl`
Then STDOUT should be:
"""
https://example.com
"""

Scenario: Install WordPress with special characters in the admin password
Given an empty directory
And WP files
Expand Down
57 changes: 51 additions & 6 deletions src/Core_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ public function is_installed( $args, $assoc_args ) {
* @param array{url: string, title: string, admin_user: string, admin_password?: string, admin_email: string, locale?: string, 'skip-email'?: bool} $assoc_args Associative arguments.
*/
public function install( $args, $assoc_args ) {
// Fix $_SERVER variables early to prevent incorrect URL detection.
// See set_server_url_vars() for details.
if ( isset( $assoc_args['url'] ) ) {
$this->set_server_url_vars( $assoc_args['url'] );
}

if ( $this->do_install( $assoc_args ) ) {
WP_CLI::success( 'WordPress installed successfully.' );
} else {
Expand Down Expand Up @@ -606,6 +612,12 @@ public function multisite_convert( $args, $assoc_args ) {
* @param array{url?: string, base: string, subdomains?: bool, title: string, admin_user: string, admin_password?: string, admin_email: string, 'skip-email'?: bool, 'skip-config'?: bool} $assoc_args Associative arguments.
*/
public function multisite_install( $args, $assoc_args ) {
// Fix $_SERVER variables early to prevent incorrect URL detection.
// See set_server_url_vars() for details.
if ( isset( $assoc_args['url'] ) ) {
$this->set_server_url_vars( $assoc_args['url'] );
}

if ( $this->do_install( $assoc_args ) ) {
WP_CLI::log( 'Created single site database tables.' );
} else {
Expand Down Expand Up @@ -664,6 +676,38 @@ private static function set_multisite_defaults( $assoc_args ) {
return array_merge( $defaults, $assoc_args );
}

/**
* Fix $_SERVER variables to prevent incorrect URL detection during installation.
*
* When WP-CLI is executed from the root of the filesystem (e.g., /wp), PHP_SELF
* and SCRIPT_NAME contain the WP-CLI executable path rather than the WordPress
* installation path. This causes WordPress's wp_guess_url() to construct incorrect
* URLs. This method overrides these variables based on the provided URL to ensure
* correct home/siteurl values during installation.
*
* @param string $url The URL to use for setting server variables.
*/
private function set_server_url_vars( $url ) {
$url_parts = Utils\parse_url( $url );
$path = isset( $url_parts['path'] ) ? $url_parts['path'] : '/';

// Ensure path represents a PHP script for proper WordPress URL detection.
$path = rtrim( $path, '/' );
if ( empty( $path ) ) {
$path = '/index.php';
} elseif ( '' === pathinfo( $path, PATHINFO_EXTENSION ) ) {
$path .= '/index.php';
}

$_SERVER['PHP_SELF'] = $path;
$_SERVER['SCRIPT_NAME'] = $path;

// Set SCRIPT_FILENAME to the actual WordPress index.php if available.
if ( file_exists( Utils\trailingslashit( ABSPATH ) . 'index.php' ) ) {
$_SERVER['SCRIPT_FILENAME'] = Utils\trailingslashit( ABSPATH ) . 'index.php';
}
}

private function do_install( $assoc_args ) {
/**
* @var \wpdb $wpdb
Expand All @@ -673,6 +717,13 @@ private function do_install( $assoc_args ) {
return false;
}

// Fix $_SERVER variables early to prevent incorrect URL detection.
// This must be done before loading any WordPress files. See set_server_url_vars().
if ( isset( $assoc_args['url'] ) ) {
WP_CLI::set_url( $assoc_args['url'] );
$this->set_server_url_vars( $assoc_args['url'] );
}

if ( true === Utils\get_flag_value( $assoc_args, 'skip-email' ) ) {
if ( ! function_exists( 'wp_new_blog_notification' ) ) {
// @phpstan-ignore function.inner
Expand All @@ -697,12 +748,6 @@ function wp_new_blog_notification() {

$args = wp_parse_args( $assoc_args, $defaults );

// Support prompting for the `--url=<url>`,
// which is normally a runtime argument
if ( isset( $assoc_args['url'] ) ) {
WP_CLI::set_url( $assoc_args['url'] );
}

$public = true;
$password = wp_slash( $args['admin_password'] );

Expand Down
Loading