-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Bug Report
- Yes, I reviewed the contribution guidelines.
- Yes, more specifically, I reviewed the guidelines on how to write clear bug reports.
Describe the current, buggy behavior
Currently, you must have a require AND wp-settings.php on the same line.
- They can use
requireorrequire_once - They can use parenthesis
require_once('....');or notrequire_once '....'; - They can use ABSPATH
require_once ABSPATH . 'wp-settings.php';or notrequire_once 'wp-settings.php'; - They can have any other whitespace or use single / double / combination of quotation
The logic for this happens in a very basic foreach loop to identify the require call in a single line:
Lines 728 to 743 in 597ae1d
| $found_wp_settings = false; | |
| $lines_to_run = []; | |
| foreach ( $wp_config_code as $line ) { | |
| if ( preg_match( '/^\s*require.+wp-settings\.php/', $line ) ) { | |
| $found_wp_settings = true; | |
| continue; | |
| } | |
| $lines_to_run[] = $line; | |
| } | |
| if ( ! $found_wp_settings ) { | |
| WP_CLI::error( 'Strange wp-config.php file: wp-settings.php is not loaded directly.' ); | |
| } |
What breaks is when you use other valid forms of PHP to require the file. This may be due to typos or preference of a developer but they all still result in a working WordPress installation and admin area but broken WP-CLI commands.
Describe how other contributors can replicate this bug
- Edit your wp-config.php file and in the wp-settings.php line at the bottom, change it to the below example
- Run any WP-CLI command like
wp db prefixorwp post list - See the error:
Error: Strange wp-config.php file: wp-settings.php is not loaded directly.
wp-config.php change:
require_once
ABSPATH . 'wp-settings.php';Also valid:
require_once
(ABSPATH . 'wp-settings.php');Describe what you expect as the correct outcome
I would expect WP-CLI to work if the WP admin area is working.
Let us know what environment you are running this on
Encountered on actual customer sites on a large host
Provide a possible solution
Maybe just do one regex check across all of the wp-config.php code instead of requiring it to have one line. This is a bit complicated since the method WP_CLI\Runner::get_wp_config_code() itself intends to get the config code to run excluding that require.
But I'd assume something like this would be better:
public function get_wp_config_code( $wp_config_path = '' ) {
if ( empty( $wp_config_path ) ) {
$wp_config_path = Utils\locate_wp_config();
}
$wp_config_code = explode( "\n", file_get_contents( $wp_config_path ) );
// Detect and strip byte-order marks (BOMs).
// This code assumes they can only be found on the first line.
foreach ( self::BYTE_ORDER_MARKS as $bom_name => $bom_sequence ) {
WP_CLI::debug( "Looking for {$bom_name} BOM", 'bootstrap' );
$length = strlen( $bom_sequence );
while ( substr( $wp_config_code[0], 0, $length ) === $bom_sequence ) {
WP_CLI::warning(
"{$bom_name} byte-order mark (BOM) detected in wp-config.php file, stripping it for parsing."
);
$wp_config_code[0] = substr( $wp_config_code[0], $length );
}
}
$wp_config_code = implode( "\n", $wp_config_code );
preg_match_all( '/^\s*(require|require_once)\s*.+wp-settings\.php.+;[ \t]*$/m', $wp_config_code, $matches );
if ( empty( $matches[0] ) ) {
WP_CLI::error( 'Strange wp-config.php file: wp-settings.php is not loaded directly.' );
}
$source = str_replace( $matches[0], '', $wp_config_code );
$source = Utils\replace_path_consts( $source, $wp_config_path );
return preg_replace( '|^\s*\<\?php\s*|', '', $source );
}