Skip to content
141 changes: 141 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 @@ -759,6 +759,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 );
Expand Down Expand Up @@ -1510,6 +1557,100 @@ 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(
'<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s"><td colspan="%s" class="plugin-update colspanchange">',
$is_active ? ' active' : ' inactive',
esc_attr( $plugin_slug . '-compat-warning' ),
esc_attr( $plugin_slug ),
esc_attr( $plugin_file ),
esc_attr( $this->get_column_count() )
);

$details_url = '';
$details_link = '';

if ( current_user_can( 'install_plugins' ) ) {
$details_url = network_admin_url(
'plugin-install.php?tab=plugin-information&plugin=' . $plugin_data['slug'] .
'&TB_iframe=true&width=600&height=550'
);

$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' ),
)
);

echo '</td></tr>';
}
}
}

/**
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 @@ -8971,10 +8971,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