Exclude the Legacy REST API plugin from the feature compatibility UI (#45610)

This commit is contained in:
Néstor Soriano 2024-03-15 11:44:17 +01:00 committed by GitHub
parent ad8f76b2e9
commit fb32ab6c5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 22 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Exclude the Legacy REST API plugin from the feature compatibility UI

View File

@ -76,6 +76,13 @@ class FeaturesController {
*/
private $force_allow_enabling_plugins = false;
/**
* List of plugins excluded from feature compatibility warnings in UI.
*
* @var string[]
*/
private $plugins_excluded_from_compatibility_ui;
/**
* Creates a new instance of the class.
*/
@ -180,10 +187,10 @@ class FeaturesController {
'is_experimental' => true,
'disable_ui' => false,
'is_legacy' => true,
'disabled' => function() {
'disabled' => function () {
return version_compare( get_bloginfo( 'version' ), '6.2', '<' );
},
'desc_tip' => function() {
'desc_tip' => function () {
$string = '';
if ( version_compare( get_bloginfo( 'version' ), '6.2', '<' ) ) {
$string = __(
@ -262,6 +269,8 @@ class FeaturesController {
final public function init( LegacyProxy $proxy, PluginUtil $plugin_util ) {
$this->proxy = $proxy;
$this->plugin_util = $plugin_util;
$this->plugins_excluded_from_compatibility_ui = $plugin_util->get_plugins_excluded_from_compatibility_ui();
}
/**
@ -285,7 +294,7 @@ class FeaturesController {
if ( ! $include_experimental ) {
$features = array_filter(
$features,
function( $feature ) {
function ( $feature ) {
return ! $feature['is_experimental'];
}
);
@ -422,7 +431,7 @@ class FeaturesController {
* @param bool $enabled_features_only True to return only names of enabled plugins.
* @return array An array having a 'compatible' and an 'incompatible' key, each holding an array of feature ids.
*/
public function get_compatible_features_for_plugin( string $plugin_name, bool $enabled_features_only = false ) : array {
public function get_compatible_features_for_plugin( string $plugin_name, bool $enabled_features_only = false ): array {
$this->verify_did_woocommerce_init( __FUNCTION__ );
$features = $this->get_feature_definitions();
@ -457,7 +466,7 @@ class FeaturesController {
* @param bool $active_only True to return only active plugins.
* @return array An array having a 'compatible' and an 'incompatible' key, each holding an array of plugin names.
*/
public function get_compatible_plugins_for_feature( string $feature_id, bool $active_only = false ) : array {
public function get_compatible_plugins_for_feature( string $feature_id, bool $active_only = false ): array {
$this->verify_did_woocommerce_init( __FUNCTION__ );
$woo_aware_plugins = $this->plugin_util->get_woocommerce_aware_plugins( $active_only );
@ -572,7 +581,7 @@ class FeaturesController {
$is_default_key = preg_match( '/^woocommerce_feature_([a-zA-Z0-9_]+)_enabled$/', $option, $matches );
$features_with_custom_keys = array_filter(
$this->get_feature_definitions(),
function( $feature ) {
function ( $feature ) {
return ! empty( $feature['option_key'] );
}
);
@ -649,13 +658,16 @@ class FeaturesController {
$features = $this->get_features( true );
$feature_ids = array_keys( $features );
usort( $feature_ids, function( $feature_id_a, $feature_id_b ) use ( $features ) {
return ( $features[ $feature_id_b ]['order'] ?? 0 ) <=> ( $features[ $feature_id_a ]['order'] ?? 0 );
} );
$feature_ids = array_keys( $features );
usort(
$feature_ids,
function ( $feature_id_a, $feature_id_b ) use ( $features ) {
return ( $features[ $feature_id_b ]['order'] ?? 0 ) <=> ( $features[ $feature_id_a ]['order'] ?? 0 );
}
);
$experimental_feature_ids = array_filter(
$feature_ids,
function( $feature_id ) use ( $features ) {
function ( $feature_id ) use ( $features ) {
return $features[ $feature_id ]['is_experimental'] ?? false;
}
);
@ -709,7 +721,7 @@ class FeaturesController {
if ( $this->verify_did_woocommerce_init() ) {
// Allow feature setting properties to be determined dynamically just before being rendered.
$feature_settings = array_map(
function( $feature_setting ) {
function ( $feature_setting ) {
foreach ( $feature_setting as $prop => $value ) {
if ( is_callable( $value ) ) {
$feature_setting[ $prop ] = call_user_func( $value );
@ -894,6 +906,8 @@ class FeaturesController {
private function get_incompatible_plugins( $feature_id, $list ) {
$incompatibles = array();
$list = array_diff_key( $list, array_flip( $this->plugins_excluded_from_compatibility_ui ) );
// phpcs:enable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
foreach ( array_keys( $list ) as $plugin_name ) {
if ( ! $this->plugin_util->is_woocommerce_aware_plugin( $plugin_name ) || ! $this->proxy->call_function( 'is_plugin_active', $plugin_name ) ) {
@ -903,7 +917,7 @@ class FeaturesController {
$compatibility = $this->get_compatible_features_for_plugin( $plugin_name );
$incompatible_with = array_filter(
array_merge( $compatibility['incompatible'], $compatibility['uncertain'] ),
function( $feature_id ) {
function ( $feature_id ) {
return ! $this->is_legacy_feature( $feature_id );
}
);
@ -941,12 +955,13 @@ class FeaturesController {
}
$incompatible_plugins = false;
$relevant_plugins = array_diff( $this->plugin_util->get_woocommerce_aware_plugins( true ), $this->plugins_excluded_from_compatibility_ui );
foreach ( $this->plugin_util->get_woocommerce_aware_plugins( true ) as $plugin ) {
foreach ( $relevant_plugins as $plugin ) {
$compatibility = $this->get_compatible_features_for_plugin( $plugin, true );
$incompatible_with = array_filter(
array_merge( $compatibility['incompatible'], $compatibility['uncertain'] ),
function( $feature_id ) {
function ( $feature_id ) {
return ! $this->is_legacy_feature( $feature_id );
}
);
@ -1060,6 +1075,10 @@ class FeaturesController {
private function handle_plugin_list_rows( $plugin_file, $plugin_data ) {
global $wp_list_table;
if ( in_array( $plugin_file, $this->plugins_excluded_from_compatibility_ui, true ) ) {
return;
}
if ( 'incompatible_with_feature' !== ArrayUtil::get_value_or_default( $_GET, 'plugin_status' ) ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}
@ -1078,7 +1097,7 @@ class FeaturesController {
$incompatible_features = array_values(
array_filter(
$incompatible_features,
function( $feature_id ) {
function ( $feature_id ) {
return ! $this->is_legacy_feature( $feature_id );
}
)

View File

@ -36,12 +36,21 @@ class PluginUtil {
*/
private $woocommerce_aware_active_plugins = null;
/**
* List of plugins excluded from feature compatibility warnings in UI.
*
* @var string[]
*/
private $plugins_excluded_from_compatibility_ui;
/**
* Creates a new instance of the class.
*/
public function __construct() {
self::add_action( 'activated_plugin', array( $this, 'handle_plugin_de_activation' ), 10, 0 );
self::add_action( 'deactivated_plugin', array( $this, 'handle_plugin_de_activation' ), 10, 0 );
$this->plugins_excluded_from_compatibility_ui = array( 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php' );
}
/**
@ -180,10 +189,11 @@ class PluginUtil {
*
* @return string Warning string.
*/
public function generate_incompatible_plugin_feature_warning( string $feature_id, array $plugin_feature_info ) : string {
public function generate_incompatible_plugin_feature_warning( string $feature_id, array $plugin_feature_info ): string {
$feature_warning = '';
$incompatibles = array_merge( $plugin_feature_info['incompatible'], $plugin_feature_info['uncertain'] );
$incompatibles = array_filter( $incompatibles, 'is_plugin_active' );
$incompatibles = array_values( array_diff( $incompatibles, $this->get_plugins_excluded_from_compatibility_ui() ) );
$incompatible_count = count( $incompatibles );
if ( $incompatible_count > 0 ) {
if ( 1 === $incompatible_count ) {
@ -232,4 +242,15 @@ class PluginUtil {
return $feature_warning;
}
/**
* Get the names of the plugins that are excluded from the feature compatibility UI.
* These plugins won't be considered as incompatible with any existing feature for the purposes
* of displaying compatibility warning in UI, even if they declare incompatibilities explicitly.
*
* @return string[] Plugin names relative to the root plugins directory.
*/
public function get_plugins_excluded_from_compatibility_ui() {
return $this->plugins_excluded_from_compatibility_ui;
}
}

View File

@ -39,7 +39,7 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
add_action(
'woocommerce_register_feature_definitions',
function( $features_controller ) {
function ( $features_controller ) {
$this->reset_features_list( $this->sut );
$features = array(
@ -187,7 +187,7 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
// No option for experimental2.
$actual = array_map(
function( $feature ) {
function ( $feature ) {
return array_intersect_key(
$feature,
array( 'is_enabled' => '' )
@ -491,7 +491,7 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
public function test_get_compatible_enabled_features_for_registered_plugin() {
add_action(
'woocommerce_register_feature_definitions',
function( $features_controller ) {
function ( $features_controller ) {
$this->reset_features_list( $this->sut );
$features = array(
@ -813,6 +813,10 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
public function get_woocommerce_aware_plugins( bool $active_only = false ): array {
return $this->active_plugins;
}
public function get_plugins_excluded_from_compatibility_ui() {
return array();
}
};
$this->register_legacy_proxy_function_mocks(
@ -828,7 +832,7 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
add_action(
'woocommerce_register_feature_definitions',
function( $features_controller ) use ( $local_sut ) {
function ( $features_controller ) use ( $local_sut ) {
$this->reset_features_list( $local_sut );
$features = array(
@ -897,6 +901,10 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
public function get_woocommerce_aware_plugins( bool $active_only = false ): array {
return $this->active_plugins;
}
public function get_plugins_excluded_from_compatibility_ui() {
return array();
}
};
// phpcs:enable
@ -912,7 +920,7 @@ class FeaturesControllerTest extends \WC_Unit_Test_Case {
add_action(
'woocommerce_register_feature_definitions',
function( $features_controller ) use ( $local_sut ) {
function ( $features_controller ) use ( $local_sut ) {
$this->reset_features_list( $local_sut );
$features = array(