Skip to content
Open
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
102 changes: 102 additions & 0 deletions src/wp-admin/includes/class-wp-plugins-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,43 @@ public function single_row( $item ) {
$compatible_php = is_php_version_compatible( $requires_php );
$compatible_wp = is_wp_version_compatible( $requires_wp );

$tested_wp = null;
$tested_compatible = true;

if ( ! empty( $plugin_data['tested'] ) ) {
// Data already present from the update transient (standard directory-based plugins).
$tested_wp = $plugin_data['tested'];
$tested_compatible = is_tested_wp_version_compatible( $tested_wp );
} elseif ( ! empty( $plugin_slug ) ) {
/*
* Single-file plugins (e.g. hello.php) are absent from the update transient because
* WordPress.org derives the slug from the folder name, and a bare filename has none.
* Fall back to a per-slug site transient so the API call happens at most once per week.
*/
$cached_tested = get_site_transient( 'plugin_tested_wp_' . $plugin_slug );

if ( false === $cached_tested ) {
if ( ! function_exists( 'plugins_api' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
}

$info = plugins_api(
'plugin_information',
array(
'slug' => $plugin_slug,
'fields' => array( 'tested' => true ),
)
);
$cached_tested = ( ! is_wp_error( $info ) && ! empty( $info->tested ) ) ? $info->tested : '';
set_site_transient( 'plugin_tested_wp_' . $plugin_slug, $cached_tested, WEEK_IN_SECONDS );
}

if ( ! empty( $cached_tested ) ) {
$tested_wp = $cached_tested;
$tested_compatible = is_tested_wp_version_compatible( $tested_wp );
}
}

$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 );
Expand Down Expand Up @@ -1297,6 +1334,71 @@ public function single_row( $item ) {
*/
do_action( 'after_plugin_row_meta', $plugin_file, $plugin_data );

if ( ! $tested_compatible ) {
global $wp_version;
$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 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 ( ! empty( $compat_message ) ) {
$details_link = '';

if ( current_user_can( 'install_plugins' ) ) {
$details_url = add_query_arg(
array(
'tab' => 'plugin-information',
'plugin' => $plugin_slug,
'TB_iframe' => 'true',
'width' => '600',
'height' => '550',
),
network_admin_url( 'plugin-install.php' )
);

$details_link = sprintf(
' <a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s">%s</a>',
esc_url( $details_url ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( __( 'More information about %s' ), $plugin_data['Name'] ) ),
__( 'View details' )
);
}

wp_admin_notice(
$compat_message . $details_link,
array(
'type' => 'warning',
'additional_classes' => array( 'notice-alt', 'inline' ),
)
);
}
}

if ( $paused ) {
$notice_text = __( 'This plugin failed to load properly and is paused during recovery mode.' );

Expand Down
35 changes: 34 additions & 1 deletion src/wp-includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -9027,10 +9027,43 @@ function is_wp_version_compatible( $required ) {
$required = substr( $trimmed, 0, -2 );
}
}

return empty( $required ) || version_compare( $version, $required, '>=' );
}

/**
* Checks compatibility with the tested WordPress version.
*
* @since 7.0.0
*
* @global string $_wp_tests_wp_version The WordPress version string. Used only in Core tests.
*
* @param string $required Maximum required WordPress version.
* @return bool True if required version is compatible, false if not.
*/
function is_tested_wp_version_compatible( $required ) {
if (
defined( 'WP_RUN_CORE_TESTS' )
&& WP_RUN_CORE_TESTS
&& isset( $GLOBALS['_wp_tests_wp_version'] )
) {
$wp_version = $GLOBALS['_wp_tests_wp_version'];
} else {
$wp_version = wp_get_wp_version();
}

// Strip off any -alpha, -RC, -beta, -src suffixes.
list( $version ) = explode( '-', $wp_version );

if ( is_string( $required ) ) {
$trimmed = trim( $required );

if ( substr_count( $trimmed, '.' ) > 1 && str_ends_with( $trimmed, '.0' ) ) {
$required = substr( $trimmed, 0, -2 );
}
}
return version_compare( $version, $required, '<=' );
}

/**
* Checks compatibility with the current PHP version.
*
Expand Down
Loading