Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Fix confusing runtime environment setup order #749

Merged
merged 14 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
39 changes: 0 additions & 39 deletions includes/CLI/Plugin_Check_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
use WordPress\Plugin_Check\Checker\Check_Repository;
use WordPress\Plugin_Check\Checker\CLI_Runner;
use WordPress\Plugin_Check\Checker\Default_Check_Repository;
use WordPress\Plugin_Check\Checker\Runtime_Check;
use WordPress\Plugin_Check\Checker\Runtime_Environment_Setup;
use WordPress\Plugin_Check\Plugin_Context;
use WordPress\Plugin_Check\Utilities\Plugin_Request_Utility;
use WP_CLI;
Expand Down Expand Up @@ -192,47 +190,28 @@ static function ( $dirs ) use ( $excluded_files ) {
);
}

$checks_to_run = array();
try {
$runner->set_experimental_flag( $options['include-experimental'] );
$runner->set_check_slugs( $checks );
$runner->set_plugin( $plugin );
$runner->set_categories( $categories );
$runner->set_slug( $options['slug'] );

$checks_to_run = $runner->get_checks_to_run();
} catch ( Exception $error ) {
WP_CLI::error( $error->getMessage() );
}

if ( $this->has_runtime_check( $checks_to_run ) ) {
WP_CLI::line( __( 'Setting up runtime environment.', 'plugin-check' ) );
$runtime_setup = new Runtime_Environment_Setup();
$runtime_setup->set_up();
}

$result = false;
// Run checks against the plugin.
try {
$result = $runner->run();
} catch ( Exception $error ) {
Plugin_Request_Utility::destroy_runner();

if ( isset( $runtime_setup ) ) {
$runtime_setup->clean_up();
WP_CLI::line( __( 'Cleaning up runtime environment.', 'plugin-check' ) );
}

WP_CLI::error( $error->getMessage() );
}

Plugin_Request_Utility::destroy_runner();

if ( isset( $runtime_setup ) ) {
$runtime_setup->clean_up();
WP_CLI::line( __( 'Cleaning up runtime environment.', 'plugin-check' ) );
}

// Get errors and warnings from the results.
$errors = array();
if ( $result && empty( $assoc_args['ignore-errors'] ) ) {
Expand Down Expand Up @@ -642,24 +621,6 @@ private function display_results( $formatter, $file_name, $file_results ) {
WP_CLI::line();
}

/**
* Checks for a Runtime_Check in a list of checks.
*
* @since 1.0.0
*
* @param array $checks An array of Check instances.
* @return bool True if a Runtime_Check exists in the array, false if not.
*/
private function has_runtime_check( array $checks ) {
foreach ( $checks as $check ) {
if ( $check instanceof Runtime_Check ) {
return true;
}
}

return false;
}

/**
* Returns check results filtered by severity level.
*
Expand Down
18 changes: 14 additions & 4 deletions includes/Checker/Abstract_Check_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,6 @@ final public function set_categories( $categories ) {
* @throws Exception Thrown exception when preparation fails.
*/
final public function prepare() {
$cleanup_functions = array();

if ( $this->initialized_early ) {
/*
* When initialized early, plugins are not loaded yet when this method is called.
Expand All @@ -334,9 +332,9 @@ final public function prepare() {
$initialize_runtime = $this->has_runtime_check( $this->get_checks_to_run() );
}

$cleanup_functions = array();
if ( $initialize_runtime ) {
$preparation = new Universal_Runtime_Preparation( $this->get_check_context() );
$cleanup_functions[] = $preparation->prepare();
$cleanup_functions = $this->initialize_runtime();
}

if ( $this->delete_plugin_folder ) {
Expand Down Expand Up @@ -489,6 +487,18 @@ final public function get_checks_to_run() {
return $collection->to_map();
}

/**
* Initializes the runtime environment so that runtime checks can be run against a separate set of database tables.
*
* @since n.e.x.t
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
*
* @return callable[] Array of cleanup functions to run after the process has completed.
*/
protected function initialize_runtime(): array {
$preparation = new Universal_Runtime_Preparation( $this->get_check_context() );
return array( $preparation->prepare() );
}

/**
* Checks whether the current environment allows for runtime checks to be used.
*
Expand Down
25 changes: 25 additions & 0 deletions includes/Checker/CLI_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,31 @@ protected function get_slug_param() {
return $slug;
}

/**
* Initializes the runtime environment so that runtime checks can be run against a separate set of database tables.
*
* @since n.e.x.t
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
*
* @return callable[] Array of cleanup functions to run after the process has completed.
*/
protected function initialize_runtime(): array {
/*
* Since for WP-CLI all checks are run in a single process, we should set up the runtime environment (i.e.
* install the separate database tables) as part of this step.
* This way it runs before the regular runtime preparations, just like it does for the AJAX based flow, where
* they are invoked in a separate request prior to the requests performing actual checks.
*/
$runtime_setup = new Runtime_Environment_Setup();
$runtime_setup->set_up();

$cleanup_functions = parent::initialize_runtime();
$cleanup_functions[] = function () use ( $runtime_setup ) {
$runtime_setup->clean_up();
};

return $cleanup_functions;
}

/**
* Checks whether the current environment allows for runtime checks to be used.
*
Expand Down
93 changes: 74 additions & 19 deletions includes/Checker/Runtime_Environment_Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@

require_once ABSPATH . '/wp-admin/includes/upgrade.php';

// Get the existing site URL.
$site_url = get_option( 'siteurl' );

// Get the existing active plugins.
$active_plugins = get_option( 'active_plugins' );

// Get the existing active theme.
$active_theme = get_option( 'stylesheet' );

// Get the existing permalink structure.
$permalink_structure = get_option( 'permalink_structure' );

Expand All @@ -48,29 +54,25 @@
add_action(
'populate_options',
static function () use ( $permalink_structure ) {
/*
* If pretty permalinks are not used, temporarily enable them by setting a permalink structure, to
* avoid flushing rewrite rules in wp_install_maybe_enable_pretty_permalinks().
* Afterwards, on the 'wp_install' action, set the original (empty) permalink structure.
*/
if ( ! $permalink_structure ) {
add_action(
'wp_install',
static function () use ( $permalink_structure ) {
update_option( 'permalink_structure', $permalink_structure );
}
);
$permalink_structure = '/%postname%/';
}
add_option( 'permalink_structure', $permalink_structure );
}
);

if ( ! isset( $_SERVER['HTTP_HOST'] ) ) {
$site_url = get_option( 'siteurl' );
$_SERVER['HTTP_HOST'] = preg_replace( '#^https?://#', '', rtrim( $site_url, '/' ) );
}

// Do not send post-install notification email, see https://github.com/WordPress/plugin-check/issues/424.
add_filter( 'pre_wp_mail', '__return_false' );

wp_install(
'Plugin Check',
'plugincheck',
'[email protected]',
false
);

remove_filter( 'pre_wp_mail', '__return_false' );

// Activate the same plugins in the test environment.
update_option( 'active_plugins', $active_plugins );
$this->install_wordpress( $site_url, $active_theme, $active_plugins );
}

// Restore the old prefix.
Expand Down Expand Up @@ -186,4 +188,57 @@

return false;
}

/**
* Installs WordPress, while providing tweaks to allow for early execution of the install process.
*
* @since n.e.x.t
*
* @param string $active_siteurl The actual site's site URL.
* @param string $active_theme The actual site's theme slug.
* @param string[] $active_plugins The actual site's list of plugin basenames.
*/
private function install_wordpress( string $active_siteurl, string $active_theme, array $active_plugins ): void {
if ( ! isset( $_SERVER['HTTP_HOST'] ) ) {
$site_url = $active_siteurl;
$_SERVER['HTTP_HOST'] = preg_replace( '#^https?://#', '', rtrim( $site_url, '/' ) );
}

// Do not send post-install notification email, see https://github.com/WordPress/plugin-check/issues/424.
add_filter( 'pre_wp_mail', '__return_false' );

// The `wp_install()` function requires the WP_DEFAULT_THEME constant to be set.
if ( ! defined( 'WP_DEFAULT_THEME' ) ) {
define( 'WP_DEFAULT_THEME', $active_theme );
}

// The `wp_install()` function requires some pluggable functions like `get_user_by()` to be loaded.
if ( ! function_exists( 'get_user_by' ) ) {
require_once ABSPATH . '/wp-includes/pluggable.php';
}

/*
* Cookie constants need to be set before installation, which normally happens immediately after
* 'muplugins_loaded', which is when the logic here typically runs. It is therefore safe to call these
* functions here already.
*/
if ( doing_action( 'muplugins_loaded' ) || ! did_action( 'muplugins_loaded' ) ) {
if ( is_multisite() ) {
ms_cookie_constants();

Check warning on line 227 in includes/Checker/Runtime_Environment_Setup.php

View check run for this annotation

Codecov / codecov/patch

includes/Checker/Runtime_Environment_Setup.php#L227

Added line #L227 was not covered by tests
}
wp_cookie_constants();
}

wp_install(
'Plugin Check',
'plugincheck',
'[email protected]',
false
);

remove_filter( 'pre_wp_mail', '__return_false' );

// Activate the same plugins in the test environment.
update_option( 'active_plugins', $active_plugins );
}
}
16 changes: 0 additions & 16 deletions tests/behat/features/plugin-check.feature
Original file line number Diff line number Diff line change
Expand Up @@ -548,14 +548,6 @@ Feature: Test that the WP-CLI command works.
# Running runtime checks, including the one from pcp-addon
When I run the WP-CLI command `plugin check foo-sample --fields=code,type --format=csv --require=./wp-content/plugins/plugin-check/cli.php`
Then STDOUT should contain:
"""
Setting up runtime environment.
"""
And STDOUT should contain:
"""
Cleaning up runtime environment.
"""
And STDOUT should contain:
"""
WordPress.WP.EnqueuedResourceParameters.NotInFooter,WARNING
"""
Expand All @@ -568,14 +560,6 @@ Feature: Test that the WP-CLI command works.
# Same again, to verify object-cache.php was properly cleared again
When I run the WP-CLI command `plugin check foo-sample --fields=code,type --format=csv --require=./wp-content/plugins/plugin-check/cli.php`
Then STDOUT should contain:
"""
Setting up runtime environment.
"""
And STDOUT should contain:
"""
Cleaning up runtime environment.
"""
And STDOUT should contain:
"""
WordPress.WP.EnqueuedResourceParameters.NotInFooter,WARNING
"""
Expand Down