diff --git a/src/wp-admin/includes/class-wp-plugins-list-table.php b/src/wp-admin/includes/class-wp-plugins-list-table.php index c4866076f984d..69afe02ab9891 100644 --- a/src/wp-admin/includes/class-wp-plugins-list-table.php +++ b/src/wp-admin/includes/class-wp-plugins-list-table.php @@ -776,6 +776,53 @@ public function single_row( $item ) { $compatible_php = is_php_version_compatible( $requires_php ); $compatible_wp = is_wp_version_compatible( $requires_wp ); + if ( ! function_exists( 'plugins_api' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; + } + + $plugin_information = plugins_api( + 'plugin_information', + array( + 'slug' => $plugin_slug, + 'fields' => array_fill_keys( + array( + 'sections', + 'rating', + 'downloaded', + 'last_updated', + 'banners', + 'icons', + 'active_installs', + 'short_description', + 'tags', + 'compatibility', + 'contributors', + 'ratings', + 'screenshots', + 'support_url', + 'added', + 'homepage', + 'download_link', + 'upgrade_notice', + 'versions', + 'business_model', + 'repository_url', + 'commercial_support_url', + 'donate_link', + 'preview_link', + ), + false + ), + ) + ); + + $tested_wp = null; + $tested_compatible = true; + + if ( ! is_wp_error( $plugin_information ) && isset( $plugin_information->tested ) ) { + $tested_compatible = is_tested_wp_version_compatible( $plugin_information->tested ); + } + $has_dependents = WP_Plugin_Dependencies::has_dependents( $plugin_file ); $has_active_dependents = WP_Plugin_Dependencies::has_active_dependents( $plugin_file ); $has_unmet_dependencies = WP_Plugin_Dependencies::has_unmet_dependencies( $plugin_file ); @@ -1527,6 +1574,106 @@ public function single_row( $item ) { * 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'. */ do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status ); + + if ( ! $tested_compatible ) { + global $wp_version; + $show_compat_warning = true; + $compat_message = sprintf( + /* translators: 1: Current WordPress version, 2: Version the plugin was tested up to. */ + __( 'This plugin has not been tested with your current version of WordPress (%1$s). It may still work, but consider checking for an update or contacting the plugin author. Last tested with WordPress %2$s.' ), + $wp_version, + $tested_wp + ); + + /** + * Filters whether to show compatibility warning for a plugin. + * + * @since 7.0.0 + * + * @param bool $show_compat_warning Whether to show the compatibility warning. + * @param string $plugin_file Path to the plugin file relative to the plugins directory. + * @param array $plugin_data An array of plugin data. See get_plugin_data() + * and the {@see 'plugin_row_meta'} filter for the list + * of possible values. + * @param string $tested_wp The WordPress version the plugin was tested up to. + * @param string $wp_version Current WordPress version. + */ + $show_compat_warning = apply_filters( + 'show_plugin_compatibility_warning', + $show_compat_warning, + $plugin_file, + $plugin_data, + $tested_wp, + $wp_version + ); + + /** + * Filters the compatibility warning message for a plugin. + * + * @since 7.0.0 + * + * @param string $compat_message The compatibility warning message. + * @param string $plugin_file Path to the plugin file relative to the plugins directory. + * @param array $plugin_data An array of plugin data. See get_plugin_data() + * and the {@see 'plugin_row_meta'} filter for the list + * of possible values. + * @param string $tested_wp The WordPress version the plugin was tested up to. + * @param string $wp_version Current WordPress version. + */ + $compat_message = apply_filters( + 'plugin_compatibility_warning_message', + $compat_message, + $plugin_file, + $plugin_data, + $tested_wp, + $wp_version + ); + + if ( $show_compat_warning && ! empty( $compat_message ) ) { + printf( + '