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
147 changes: 147 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,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(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this greatly slow down accessing the plugins screen, if every row rendering every row will involve a plugins_api() call?

'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 @@ -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
);
Comment on lines +1588 to +1608
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this filter needed? Couldn't a plugin just filter plugin_compatibility_warning_message to be an empty string if they don't want to show the message?


/**
* 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">',
esc_attr( $is_active ? 'active' : 'inactive' ),
esc_attr( $plugin_slug . '-compat-warning' ),
esc_attr( $plugin_slug ),
esc_attr( $plugin_file ),
esc_attr( $this->get_column_count() )
);
Comment on lines +1633 to +1640
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is the best way to integrate this information. I think it would make sense to show where the after_plugin_row_meta action fires.


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

if ( current_user_can( 'install_plugins' ) ) {
$details_url = add_query_arg(
network_admin_url( 'plugin-install.php' ),
array(
'tab' => 'plugin-information',
'plugin' => urlencode( $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 @@ -8998,10 +8998,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