File: //usr/local/wp/php/WP_CLI/Context/Admin.php
<?php
namespace WP_CLI\Context;
use WP_CLI;
use WP_CLI\Context;
use WP_Session_Tokens;
/**
* Context which simulates the administrator backend.
*/
final class Admin implements Context {
/**
* Process the context to set up the environment correctly.
*
* @param array $config Associative array of configuration data.
* @return void
*/
public function process( $config ) {
if ( defined( 'WP_ADMIN' ) ) {
if ( ! WP_ADMIN ) {
WP_CLI::warning( 'Could not fake admin request.' );
}
return;
}
WP_CLI::debug( 'Faking an admin request', Context::DEBUG_GROUP );
// Define `WP_ADMIN` as being true. This causes the helper method
// `is_admin()` to return true as well.
define( 'WP_ADMIN', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
// Set a fake entry point to ensure wp-includes/vars.php does not throw
// notices/errors. This will be reflected in the global `$pagenow`
// variable being set to 'wp-cli-fake-admin-file.php'.
$_SERVER['PHP_SELF'] = '/wp-admin/wp-cli-fake-admin-file.php';
// Bootstrap the WordPress administration area.
WP_CLI::add_wp_hook(
'init',
function () {
$this->log_in_as_admin_user();
$this->load_admin_environment();
},
defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : -2147483648, // phpcs:ignore PHPCompatibility.Constants.NewConstants.php_int_minFound
0
);
}
/**
* Ensure the current request is done under a logged-in administrator
* account.
*
* A lot of premium plugins/themes have their custom update routines locked
* behind an is_admin() call.
*
* @return void
*/
private function log_in_as_admin_user() {
// TODO: Add logic to find an administrator user.
$admin_user_id = 1;
wp_set_current_user( $admin_user_id );
$expiration = time() + DAY_IN_SECONDS;
$_COOKIE[ AUTH_COOKIE ] = wp_generate_auth_cookie(
$admin_user_id,
$expiration,
'auth'
);
$_COOKIE[ SECURE_AUTH_COOKIE ] = wp_generate_auth_cookie(
$admin_user_id,
$expiration,
'secure_auth'
);
}
/**
* Load the admin environment.
*
* This tries to load `wp-admin/admin.php` while trying to avoid issues
* like re-loading the wp-config.php file (which redeclares constants).
*
* To make this work across WordPress versions, we use the actual file and
* modify it on-the-fly.
*
* @global string $hook_suffix
* @global string $pagenow
* @global int $wp_db_version
* @global array $_wp_submenu_nopriv
*
* @return void
*/
private function load_admin_environment() {
global $hook_suffix, $pagenow, $wp_db_version, $_wp_submenu_nopriv;
if ( ! isset( $hook_suffix ) ) {
$hook_suffix = 'index'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
// Make sure we don't trigger a DB upgrade as that tries to redirect
// the page.
$wp_db_version = (int) get_option( 'db_version' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
// Ensure WP does not iterate over an undefined variable in
// `user_can_access_admin_page()`.
if ( ! isset( $_wp_submenu_nopriv ) ) {
$_wp_submenu_nopriv = []; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
$admin_php_file = file_get_contents( ABSPATH . 'wp-admin/admin.php' );
// First we remove the opening and closing PHP tags.
$admin_php_file = preg_replace( '/^<\?php\s+/', '', $admin_php_file );
$admin_php_file = preg_replace( '/\s+\?>$/', '', $admin_php_file );
// Then we remove the loading of either wp-config.php or wp-load.php.
$admin_php_file = preg_replace( '/^\s*(?:include|require).*[\'"]\/?wp-(?:load|config)\.php[\'"]\s*\)?;\s*$/m', '', $admin_php_file );
// We also remove the authentication redirect.
$admin_php_file = preg_replace( '/^\s*auth_redirect\(\);$/m', '', $admin_php_file );
// Finally, we avoid sending headers.
$admin_php_file = preg_replace( '/^\s*nocache_headers\(\);$/m', '', $admin_php_file );
$_GET['noheader'] = true;
eval( $admin_php_file ); // phpcs:ignore Squiz.PHP.Eval.Discouraged
}
}