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

Add Categories and Checks CLI commands #339

Merged
merged 3 commits into from
Jan 5, 2024
Merged
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
209 changes: 175 additions & 34 deletions includes/CLI/Plugin_Check_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
namespace WordPress\Plugin_Check\CLI;

use Exception;
use WordPress\Plugin_Check\Checker\Check_Categories;
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;
Expand Down Expand Up @@ -114,20 +116,17 @@ public function __construct( Plugin_Context $plugin_context ) {
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function check( $args, $assoc_args ) {
/*
* Bail early if the Plugin Checker is not activated.
*
* If the Plugin Checker is not activated, it will throw an error and
* CLI commands won't be usable.
*/
if ( is_plugin_inactive( $this->plugin_context->basename() ) ) {
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
WP_CLI::error(
__( 'Plugin Checker is not active.', 'plugin-check' )
);
}

// Get options based on the CLI arguments.
$options = $this->get_options( $assoc_args );
$options = $this->get_options(
$assoc_args,
array(
'checks' => '',
'format' => 'table',
'ignore-warnings' => false,
'ignore-errors' => false,
'include-experimental' => false,
)
);

// Create the plugin and checks array from CLI arguments.
$plugin = isset( $args[0] ) ? $args[0] : '';
Expand Down Expand Up @@ -210,8 +209,11 @@ static function ( $dirs ) use ( $excluded_directories ) {
$warnings = $result->get_warnings();
}

// Default fields.
$default_fields = $this->get_check_default_fields( $assoc_args );

// Get formatter.
$formatter = $this->get_formatter( $assoc_args );
$formatter = $this->get_formatter( $assoc_args, $default_fields );

// Print the formatted results.
// Go over all files with errors first and print them, combined with any warnings in the same file.
Expand All @@ -233,24 +235,150 @@ static function ( $dirs ) use ( $excluded_directories ) {
}

/**
* Validates the associative arguments.
* Lists the available checks for plugins.
*
* ## OPTIONS
*
* [--fields=<fields>]
* : Limit displayed results to a subset of fields provided.
*
* [--format=<format>]
* : Format to display the results. Options are table, csv, and json. The default will be a table.
* ---
* default: table
* options:
* - table
* - csv
* - json
* ---
*
* @subcommand list-checks
*
* @since n.e.x.t
*
* @param array $args List of the positional arguments.
* @param array $assoc_args List of the associative arguments.
* @return array List of the associative arguments.
*
* @throws WP_CLI\ExitException Show error if plugin not found.
* @throws WP_CLI\ExitException Show error if invalid format argument.
*/
private function get_options( $assoc_args ) {
$defaults = array(
'checks' => '',
'format' => 'table',
'ignore-warnings' => false,
'ignore-errors' => false,
'include-experimental' => false,
public function list_checks( $args, $assoc_args ) {
$check_repo = new Default_Check_Repository();

$all_checks = array();

foreach ( $check_repo->get_checks() as $key => $check ) {
$item = array();

$item['slug'] = $key;
$item['stability'] = strtolower( $check->get_stability() );
$item['category'] = join( ', ', $check->get_categories() );

$all_checks[] = $item;
}

// Get options based on the CLI arguments.
$options = $this->get_options( $assoc_args, array( 'format' => 'table' ) );

// Get formatter.
$formatter = $this->get_formatter(
$options,
array(
'slug',
'category',
'stability',
)
);

// Display results.
$formatter->display_items( $all_checks );
}

/**
* Lists the available check categories for plugins.
*
* ## OPTIONS
*
* [--fields=<fields>]
* : Limit displayed results to a subset of fields provided.
*
* [--format=<format>]
* : Format to display the results. Options are table, csv, and json. The default will be a table.
* ---
* default: table
* options:
* - table
* - csv
* - json
* ---
*
* ## EXAMPLES
*
* wp plugin list-check-categories
* wp plugin list-check-categories --format=json
*
* @subcommand list-check-categories
*
* @since n.e.x.t
*
* @param array $args List of the positional arguments.
* @param array $assoc_args List of the associative arguments.
*
* @throws WP_CLI\ExitException Show error if invalid format argument.
*/
public function list_check_categories( $args, $assoc_args ) {
// Get options based on the CLI arguments.
$options = $this->get_options( $assoc_args, array( 'format' => 'table' ) );

// Get check categories details.
$categories = $this->get_check_categories();

// Get formatter.
$formatter = $this->get_formatter(
$options,
array(
'name',
'slug',
)
);

// Display results.
$formatter->display_items( $categories );
}

/**
* Returns check categories details.
*
* @since n.e.x.t
*
* @return array List of the check categories.
*/
private function get_check_categories() {
$check_categories = new Check_Categories();
$categories_slugs = $check_categories->get_categories();

return array_map(
function ( $slug ) {
return array(
'slug' => $slug,
'name' => ucfirst( str_replace( '_', ' ', $slug ) ),
);
},
$categories_slugs
);
}

/**
* Validates the associative arguments.
*
* @since n.e.x.t
*
* @param array $assoc_args List of the associative arguments.
* @param array $defaults List of the default arguments.
* @return array List of the associative arguments.
*
* @throws WP_CLI\ExitException Show error if invalid format argument.
*/
private function get_options( $assoc_args, $defaults ) {
$options = wp_parse_args( $assoc_args, $defaults );

if ( ! in_array( $options['format'], $this->output_formats, true ) ) {
Expand All @@ -271,21 +399,37 @@ private function get_options( $assoc_args ) {
*
* @since n.e.x.t
*
* @param array $assoc_args Associative arguments.
* @param array $assoc_args Associative arguments.
* @param array $default_fields Default fields.
* @return WP_CLI\Formatter The formatter instance.
*/
private function get_formatter( $assoc_args ) {
private function get_formatter( $assoc_args, $default_fields ) {
if ( isset( $assoc_args['fields'] ) ) {
$default_fields = wp_parse_args( $assoc_args['fields'], $default_fields );
}

return new WP_CLI\Formatter(
$assoc_args,
$default_fields
);
}

/**
* Returns check default fields.
*
* @since n.e.x.t
*
* @param array $assoc_args Associative arguments.
* @return array Default fields.
*/
private function get_check_default_fields( $assoc_args ) {
ernilambar marked this conversation as resolved.
Show resolved Hide resolved
$default_fields = array(
'line',
'column',
'code',
'message',
);

if ( isset( $assoc_args['fields'] ) ) {
$default_fields = wp_parse_args( $assoc_args['fields'], $default_fields );
}

// If both errors and warnings are included, display the type of each result too.
if ( empty( $assoc_args['ignore_errors'] ) && empty( $assoc_args['ignore_warnings'] ) ) {
$default_fields = array(
Expand All @@ -297,10 +441,7 @@ private function get_formatter( $assoc_args ) {
);
}

return new WP_CLI\Formatter(
$assoc_args,
$default_fields
);
return $default_fields;
}

/**
Expand Down
46 changes: 2 additions & 44 deletions includes/Checker/Abstract_Check_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ abstract protected function get_categories_param();
* @since n.e.x.t
*/
final public function __construct() {
$this->initialized_early = ! did_action( 'muplugins_loaded' );
$this->register_checks();
$this->initialized_early = ! did_action( 'muplugins_loaded' );
$this->check_repository = new Default_Check_Repository();
$this->runtime_environment = new Runtime_Environment_Setup();
}

Expand Down Expand Up @@ -529,48 +529,6 @@ private function get_check_context() {
return new Check_Context( WP_PLUGIN_DIR . '/' . $this->get_plugin_basename() );
}

/**
* Registers Checks to the Check_Repository.
*
* @since n.e.x.t
*/
private function register_checks() {
$this->check_repository = new Default_Check_Repository();

/**
* Filters the available plugin check classes.
*
* @since n.e.x.t
*
* @param array $checks An array map of check slugs to Check instances.
*/
$checks = apply_filters(
'wp_plugin_check_checks',
array(
'i18n_usage' => new Checks\I18n_Usage_Check(),
'enqueued_scripts_size' => new Checks\Enqueued_Scripts_Size_Check(),
'code_obfuscation' => new Checks\Code_Obfuscation_Check(),
'file_type' => new Checks\File_Type_Check(),
'plugin_header_text_domain' => new Checks\Plugin_Header_Text_Domain_Check(),
'late_escaping' => new Checks\Late_Escaping_Check(),
'plugin_updater' => new Checks\Plugin_Updater_Check(),
'plugin_review_phpcs' => new Checks\Plugin_Review_PHPCS_Check(),
'direct_db_queries' => new Checks\Direct_DB_Queries_Check(),
'performant_wp_query_params' => new Checks\Performant_WP_Query_Params_Check(),
'enqueued_scripts_in_footer' => new Checks\Enqueued_Scripts_In_Footer_Check(),
'plugin_readme' => new Checks\Plugin_Readme_Check(),
'enqueued_styles_scope' => new Checks\Enqueued_Styles_Scope_Check(),
'localhost' => new Checks\Localhost_Check(),
'no_unfiltered_uploads' => new Checks\No_Unfiltered_Uploads_Check(),
'trademarks' => new Checks\Trademarks_Check(),
)
);

foreach ( $checks as $slug => $check ) {
$this->check_repository->register_check( $slug, $check );
}
}

/**
* Sets the runtime environment setup.
*
Expand Down
Loading