wp/wp-admin/includes/class-wp-plugins-list-table.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
--- a/wp/wp-admin/includes/class-wp-plugins-list-table.php	Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-admin/includes/class-wp-plugins-list-table.php	Tue Sep 27 16:37:53 2022 +0200
@@ -739,6 +739,12 @@
 		$restrict_network_active = false;
 		$restrict_network_only   = false;
 
+		$requires_php = isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : null;
+		$requires_wp  = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null;
+
+		$compatible_php = is_php_version_compatible( $requires_php );
+		$compatible_wp  = is_wp_version_compatible( $requires_wp );
+
 		if ( 'mustuse' === $context ) {
 			$is_active = true;
 		} elseif ( 'dropins' === $context ) {
@@ -792,14 +798,21 @@
 					}
 				} else {
 					if ( current_user_can( 'manage_network_plugins' ) ) {
-						$actions['activate'] = sprintf(
-							'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
-							wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ) . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ),
-							esc_attr( $plugin_id_attr ),
-							/* translators: %s: Plugin name. */
-							esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
-							__( 'Network Activate' )
-						);
+						if ( $compatible_php && $compatible_wp ) {
+							$actions['activate'] = sprintf(
+								'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
+								wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ) . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ),
+								esc_attr( $plugin_id_attr ),
+								/* translators: %s: Plugin name. */
+								esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
+								__( 'Network Activate' )
+							);
+						} else {
+							$actions['activate'] = sprintf(
+								'<span>%s</span>',
+								_x( 'Cannot Activate', 'plugin' )
+							);
+						}
 					}
 
 					if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) {
@@ -846,14 +859,21 @@
 					}
 				} else {
 					if ( current_user_can( 'activate_plugin', $plugin_file ) ) {
-						$actions['activate'] = sprintf(
-							'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
-							wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ) . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ),
-							esc_attr( $plugin_id_attr ),
-							/* translators: %s: Plugin name. */
-							esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
-							__( 'Activate' )
-						);
+						if ( $compatible_php && $compatible_wp ) {
+							$actions['activate'] = sprintf(
+								'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
+								wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ) . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ),
+								esc_attr( $plugin_id_attr ),
+								/* translators: %s: Plugin name. */
+								esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
+								__( 'Activate' )
+							);
+						} else {
+							$actions['activate'] = sprintf(
+								'<span>%s</span>',
+								_x( 'Cannot Activate', 'plugin' )
+							);
+						}
 					}
 
 					if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
@@ -879,12 +899,15 @@
 			 *
 			 * @since 3.1.0
 			 *
-			 * @param string[] $actions     An array of plugin action links. By default this can include 'activate',
-			 *                              'deactivate', and 'delete'.
+			 * @param string[] $actions     An array of plugin action links. By default this can include
+			 *                              'activate', 'deactivate', and 'delete'.
 			 * @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()`.
-			 * @param string   $context     The plugin context. By default this can include 'all', 'active', 'inactive',
-			 *                              'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
+			 * @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   $context     The plugin context. By default this can include 'all',
+			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
+			 *                              'mustuse', 'dropins', and 'search'.
 			 */
 			$actions = apply_filters( 'network_admin_plugin_action_links', $actions, $plugin_file, $plugin_data, $context );
 
@@ -896,12 +919,15 @@
 			 *
 			 * @since 3.1.0
 			 *
-			 * @param string[] $actions     An array of plugin action links. By default this can include 'activate',
-			 *                              'deactivate', and 'delete'.
+			 * @param string[] $actions     An array of plugin action links. By default this can include
+			 *                              'activate', 'deactivate', and 'delete'.
 			 * @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()`.
-			 * @param string   $context     The plugin context. By default this can include 'all', 'active', 'inactive',
-			 *                              'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
+			 * @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   $context     The plugin context. By default this can include 'all',
+			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
+			 *                              'mustuse', 'dropins', and 'search'.
 			 */
 			$actions = apply_filters( "network_admin_plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );
 
@@ -914,13 +940,16 @@
 			 * @since 2.6.0 The `$context` parameter was added.
 			 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
 			 *
-			 * @param string[] $actions     An array of plugin action links. By default this can include 'activate',
-			 *                              'deactivate', and 'delete'. With Multisite active this can also include
-			 *                              'network_active' and 'network_only' items.
+			 * @param string[] $actions     An array of plugin action links. By default this can include
+			 *                              'activate', 'deactivate', and 'delete'. With Multisite active
+			 *                              this can also include 'network_active' and 'network_only' items.
 			 * @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()`.
-			 * @param string   $context     The plugin context. By default this can include 'all', 'active', 'inactive',
-			 *                              'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
+			 * @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   $context     The plugin context. By default this can include 'all',
+			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
+			 *                              'mustuse', 'dropins', and 'search'.
 			 */
 			$actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context );
 
@@ -933,22 +962,23 @@
 			 * @since 2.7.0
 			 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
 			 *
-			 * @param string[] $actions     An array of plugin action links. By default this can include 'activate',
-			 *                              'deactivate', and 'delete'. With Multisite active this can also include
-			 *                              'network_active' and 'network_only' items.
+			 * @param string[] $actions     An array of plugin action links. By default this can include
+			 *                              'activate', 'deactivate', and 'delete'. With Multisite active
+			 *                              this can also include 'network_active' and 'network_only' items.
 			 * @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()`.
-			 * @param string   $context     The plugin context. By default this can include 'all', 'active', 'inactive',
-			 *                              'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
+			 * @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   $context     The plugin context. By default this can include 'all',
+			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
+			 *                              'mustuse', 'dropins', and 'search'.
 			 */
 			$actions = apply_filters( "plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );
 
 		}
 
-		$requires_php   = isset( $plugin_data['requires_php'] ) ? $plugin_data['requires_php'] : null;
-		$compatible_php = is_php_version_compatible( $requires_php );
-		$class          = $is_active ? 'active' : 'inactive';
-		$checkbox_id    = 'checkbox_' . md5( $plugin_file );
+		$class       = $is_active ? 'active' : 'inactive';
+		$checkbox_id = 'checkbox_' . md5( $plugin_file );
 
 		if ( $restrict_network_active || $restrict_network_only || in_array( $status, array( 'mustuse', 'dropins' ), true ) || ! $compatible_php ) {
 			$checkbox = '';
@@ -968,7 +998,9 @@
 			$plugin_name = $plugin_data['Name'];
 		}
 
-		if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) ) {
+		if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] )
+			|| ! $compatible_php || ! $compatible_wp
+		) {
 			$class .= ' update';
 		}
 
@@ -1046,9 +1078,13 @@
 							__( 'View details' )
 						);
 					} elseif ( ! empty( $plugin_data['PluginURI'] ) ) {
+						/* translators: %s: Plugin name. */
+						$aria_label = sprintf( __( 'Visit plugin site for %s' ), $plugin_name );
+
 						$plugin_meta[] = sprintf(
-							'<a href="%s">%s</a>',
+							'<a href="%s" aria-label="%s">%s</a>',
 							esc_url( $plugin_data['PluginURI'] ),
+							esc_attr( $aria_label ),
 							__( 'Visit plugin site' )
 						);
 					}
@@ -1061,7 +1097,39 @@
 					 * @param string[] $plugin_meta An array of the plugin's metadata, including
 					 *                              the version, author, author URI, and plugin URI.
 					 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
-					 * @param array    $plugin_data An array of plugin data.
+					 * @param array    $plugin_data {
+					 *     An array of plugin data.
+					 *
+					 *     @type string   $id               Plugin ID, e.g. `w.org/plugins/[plugin-name]`.
+					 *     @type string   $slug             Plugin slug.
+					 *     @type string   $plugin           Plugin basename.
+					 *     @type string   $new_version      New plugin version.
+					 *     @type string   $url              Plugin URL.
+					 *     @type string   $package          Plugin update package URL.
+					 *     @type string[] $icons            An array of plugin icon URLs.
+					 *     @type string[] $banners          An array of plugin banner URLs.
+					 *     @type string[] $banners_rtl      An array of plugin RTL banner URLs.
+					 *     @type string   $requires         The version of WordPress which the plugin requires.
+					 *     @type string   $tested           The version of WordPress the plugin is tested against.
+					 *     @type string   $requires_php     The version of PHP which the plugin requires.
+					 *     @type string   $upgrade_notice   The upgrade notice for the new plugin version.
+					 *     @type bool     $update-supported Whether the plugin supports updates.
+					 *     @type string   $Name             The human-readable name of the plugin.
+					 *     @type string   $PluginURI        Plugin URI.
+					 *     @type string   $Version          Plugin version.
+					 *     @type string   $Description      Plugin description.
+					 *     @type string   $Author           Plugin author.
+					 *     @type string   $AuthorURI        Plugin author URI.
+					 *     @type string   $TextDomain       Plugin textdomain.
+					 *     @type string   $DomainPath       Relative path to the plugin's .mo file(s).
+					 *     @type bool     $Network          Whether the plugin can only be activated network-wide.
+					 *     @type string   $RequiresWP       The version of WordPress which the plugin requires.
+					 *     @type string   $RequiresPHP      The version of PHP which the plugin requires.
+					 *     @type string   $UpdateURI        ID of the plugin for update purposes, should be a URI.
+					 *     @type string   $Title            The human-readable title of the plugin.
+					 *     @type string   $AuthorName       Plugin author's name.
+					 *     @type bool     $update           Whether there's an available update. Default null.
+					 * }
 					 * @param string   $status      Status filter currently applied to the plugin list. Possible
 					 *                              values are: 'all', 'active', 'inactive', 'recently_activated',
 					 *                              'upgrade', 'mustuse', 'dropins', 'search', 'paused',
@@ -1157,10 +1225,13 @@
 					 *
 					 * @since 5.5.0
 					 *
-					 * @param string $html        The HTML of the plugin's auto-update column content, including
-					 *                            toggle auto-update action links and time to next update.
+					 * @param string $html        The HTML of the plugin's auto-update column content,
+					 *                            including toggle auto-update action links and
+					 *                            time to next update.
 					 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
-					 * @param array  $plugin_data An array of plugin data.
+					 * @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.
 					 */
 					echo apply_filters( 'plugin_auto_update_setting_html', $html, $plugin_file, $plugin_data );
 
@@ -1180,7 +1251,9 @@
 					 *
 					 * @param string $column_name Name of the column.
 					 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
-					 * @param array  $plugin_data An array of plugin data.
+					 * @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.
 					 */
 					do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data );
 
@@ -1190,18 +1263,77 @@
 
 		echo '</tr>';
 
+		if ( ! $compatible_php || ! $compatible_wp ) {
+			printf(
+				'<tr class="plugin-update-tr">' .
+				'<td colspan="%s" class="plugin-update colspanchange">' .
+				'<div class="update-message notice inline notice-error notice-alt"><p>',
+				esc_attr( $this->get_column_count() )
+			);
+
+			if ( ! $compatible_php && ! $compatible_wp ) {
+				_e( 'This plugin does not work with your versions of WordPress and PHP.' );
+				if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
+					printf(
+						/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
+						' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
+						self_admin_url( 'update-core.php' ),
+						esc_url( wp_get_update_php_url() )
+					);
+					wp_update_php_annotation( '</p><p><em>', '</em>' );
+				} elseif ( current_user_can( 'update_core' ) ) {
+					printf(
+						/* translators: %s: URL to WordPress Updates screen. */
+						' ' . __( '<a href="%s">Please update WordPress</a>.' ),
+						self_admin_url( 'update-core.php' )
+					);
+				} elseif ( current_user_can( 'update_php' ) ) {
+					printf(
+						/* translators: %s: URL to Update PHP page. */
+						' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
+						esc_url( wp_get_update_php_url() )
+					);
+					wp_update_php_annotation( '</p><p><em>', '</em>' );
+				}
+			} elseif ( ! $compatible_wp ) {
+				_e( 'This plugin does not work with your version of WordPress.' );
+				if ( current_user_can( 'update_core' ) ) {
+					printf(
+						/* translators: %s: URL to WordPress Updates screen. */
+						' ' . __( '<a href="%s">Please update WordPress</a>.' ),
+						self_admin_url( 'update-core.php' )
+					);
+				}
+			} elseif ( ! $compatible_php ) {
+				_e( 'This plugin does not work with your version of PHP.' );
+				if ( current_user_can( 'update_php' ) ) {
+					printf(
+						/* translators: %s: URL to Update PHP page. */
+						' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
+						esc_url( wp_get_update_php_url() )
+					);
+					wp_update_php_annotation( '</p><p><em>', '</em>' );
+				}
+			}
+
+			echo '</p></div></td></tr>';
+		}
+
 		/**
 		 * Fires after each row in the Plugins list table.
 		 *
 		 * @since 2.3.0
-		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled' to possible values for `$status`.
+		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
+		 *              to possible values for `$status`.
 		 *
 		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
-		 * @param array  $plugin_data An array of plugin data.
-		 * @param string $status      Status filter currently applied to the plugin list. Possible
-		 *                            values are: 'all', 'active', 'inactive', 'recently_activated',
-		 *                            'upgrade', 'mustuse', 'dropins', 'search', 'paused',
-		 *                            'auto-update-enabled', 'auto-update-disabled'.
+		 * @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 $status      Status filter currently applied to the plugin list.
+		 *                            Possible values are: 'all', 'active', 'inactive',
+		 *                            'recently_activated', 'upgrade', 'mustuse', 'dropins',
+		 *                            'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
 		 */
 		do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
 
@@ -1212,14 +1344,17 @@
 		 * to the plugin file, relative to the plugins directory.
 		 *
 		 * @since 2.7.0
-		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled' to possible values for `$status`.
+		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
+		 *              to possible values for `$status`.
 		 *
 		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
-		 * @param array  $plugin_data An array of plugin data.
-		 * @param string $status      Status filter currently applied to the plugin list. Possible
-		 *                            values are: 'all', 'active', 'inactive', 'recently_activated',
-		 *                            'upgrade', 'mustuse', 'dropins', 'search', 'paused',
-		 *                            'auto-update-enabled', 'auto-update-disabled'.
+		 * @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 $status      Status filter currently applied to the plugin list.
+		 *                            Possible values are: 'all', 'active', 'inactive',
+		 *                            'recently_activated', 'upgrade', 'mustuse', 'dropins',
+		 *                            'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
 		 */
 		do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
 	}