--- a/wp/wp-admin/includes/plugin.php Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-admin/includes/plugin.php Wed Sep 21 18:19:35 2022 +0200
@@ -44,6 +44,7 @@
*
* @since 1.5.0
* @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers.
+ * @since 5.8.0 Added support for `Update URI` header.
*
* @param string $plugin_file Absolute path to the main plugin file.
* @param bool $markup Optional. If the returned data should have HTML markup applied.
@@ -63,6 +64,7 @@
* @type bool $Network Whether the plugin can only be activated network-wide.
* @type string $RequiresWP Minimum required version of WordPress.
* @type string $RequiresPHP Minimum required version of PHP.
+ * @type string $UpdateURI ID of the plugin for update purposes, should be a URI.
* }
*/
function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
@@ -79,6 +81,7 @@
'Network' => 'Network',
'RequiresWP' => 'Requires at least',
'RequiresPHP' => 'Requires PHP',
+ 'UpdateURI' => 'Update URI',
// Site Wide Only is deprecated in favor of Network.
'_sitewide' => 'Site Wide Only',
);
@@ -293,7 +296,7 @@
}
// Files in wp-content/plugins directory.
- $plugins_dir = @ opendir( $plugin_root );
+ $plugins_dir = @opendir( $plugin_root );
$plugin_files = array();
if ( $plugins_dir ) {
@@ -303,7 +306,7 @@
}
if ( is_dir( $plugin_root . '/' . $file ) ) {
- $plugins_subdir = @ opendir( $plugin_root . '/' . $file );
+ $plugins_subdir = @opendir( $plugin_root . '/' . $file );
if ( $plugins_subdir ) {
while ( ( $subfile = readdir( $plugins_subdir ) ) !== false ) {
@@ -651,7 +654,9 @@
return $requirements;
}
- if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current, true ) ) ) {
+ if ( $network_wide && ! isset( $current[ $plugin ] )
+ || ! $network_wide && ! in_array( $plugin, $current, true )
+ ) {
if ( ! empty( $redirect ) ) {
// We'll override this later if the plugin can be included without fatal error.
wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) );
@@ -659,14 +664,8 @@
ob_start();
- if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
- define( 'WP_SANDBOX_SCRAPING', true );
- }
-
- wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
- $_wp_plugin_file = $plugin;
- include_once WP_PLUGIN_DIR . '/' . $plugin;
- $plugin = $_wp_plugin_file; // Avoid stomping of the $plugin variable in a plugin.
+ // Load the plugin to test whether it throws any errors.
+ plugin_sandbox_scrape( $plugin );
if ( ! $silent ) {
/**
@@ -730,6 +729,7 @@
$output = ob_get_clean();
return new WP_Error( 'unexpected_output', __( 'The plugin generated unexpected output.' ), $output );
}
+
ob_end_clean();
}
@@ -764,7 +764,7 @@
continue;
}
- $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin );
+ $network_deactivating = ( false !== $network_wide ) && is_plugin_active_for_network( $plugin );
if ( ! $silent ) {
/**
@@ -978,7 +978,7 @@
// If plugin is in its own directory, recursively delete the directory.
// Base check on if plugin includes directory separator AND that it's not the root plugin folder.
- if ( strpos( $plugin_file, '/' ) && $this_plugin_dir != $plugins_dir ) {
+ if ( strpos( $plugin_file, '/' ) && $this_plugin_dir !== $plugins_dir ) {
$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
} else {
$deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file );
@@ -999,8 +999,13 @@
continue;
}
+ $plugin_slug = dirname( $plugin_file );
+
+ if ( 'hello.php' === $plugin_file ) {
+ $plugin_slug = 'hello-dolly';
+ }
+
// Remove language files, silently.
- $plugin_slug = dirname( $plugin_file );
if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) {
$translations = $plugin_translations[ $plugin_slug ];
@@ -1114,12 +1119,10 @@
* Uses the information from `Requires at least` and `Requires PHP` headers
* defined in the plugin's main PHP file.
*
- * If the headers are not present in the plugin's main PHP file,
- * `readme.txt` is also checked as a fallback.
- *
* @since 5.2.0
* @since 5.3.0 Added support for reading the headers from the plugin's
* main PHP file, with `readme.txt` as a fallback.
+ * @since 5.8.0 Removed support for using `readme.txt` as a fallback.
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
* @return true|WP_Error True if requirements are met, WP_Error on failure.
@@ -1132,26 +1135,11 @@
'requires_php' => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '',
);
- $readme_file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/readme.txt';
-
- if ( file_exists( $readme_file ) ) {
- $readme_headers = get_file_data(
- $readme_file,
- array(
- 'requires' => 'Requires at least',
- 'requires_php' => 'Requires PHP',
- ),
- 'plugin'
- );
-
- $requirements = array_merge( $readme_headers, $requirements );
- }
-
$compatible_wp = is_wp_version_compatible( $requirements['requires'] );
$compatible_php = is_php_version_compatible( $requirements['requires_php'] );
- /* translators: %s: URL to Update PHP page. */
$php_update_message = '</p><p>' . sprintf(
+ /* translators: %s: URL to Update PHP page. */
__( '<a href="%s">Learn more about updating PHP</a>.' ),
esc_url( wp_get_update_php_url() )
);
@@ -1229,7 +1217,8 @@
* @since 2.7.0
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
- * @return true True if a plugin's uninstall.php file has been found and included.
+ * @return true|void True if a plugin's uninstall.php file has been found and included.
+ * Void otherwise.
*/
function uninstall_plugin( $plugin ) {
$file = plugin_basename( $plugin );
@@ -1414,9 +1403,9 @@
* parent file someone is trying to link back to the parent manually. In
* this case, don't automatically add a link back to avoid duplication.
*/
- if ( ! isset( $submenu[ $parent_slug ] ) && $menu_slug != $parent_slug ) {
+ if ( ! isset( $submenu[ $parent_slug ] ) && $menu_slug !== $parent_slug ) {
foreach ( (array) $menu as $parent_menu ) {
- if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) ) {
+ if ( $parent_menu[2] === $parent_slug && current_user_can( $parent_menu[1] ) ) {
$submenu[ $parent_slug ][] = array_slice( $parent_menu, 0, 4 );
}
}
@@ -1761,13 +1750,13 @@
* @global array $menu
*
* @param string $menu_slug The slug of the menu.
- * @return array|bool The removed menu on success, false if not found.
+ * @return array|false The removed menu on success, false if not found.
*/
function remove_menu_page( $menu_slug ) {
global $menu;
foreach ( $menu as $i => $item ) {
- if ( $menu_slug == $item[2] ) {
+ if ( $menu_slug === $item[2] ) {
unset( $menu[ $i ] );
return $item;
}
@@ -1785,7 +1774,7 @@
*
* @param string $menu_slug The slug for the parent menu.
* @param string $submenu_slug The slug of the submenu.
- * @return array|bool The removed submenu on success, false if not found.
+ * @return array|false The removed submenu on success, false if not found.
*/
function remove_submenu_page( $menu_slug, $submenu_slug ) {
global $submenu;
@@ -1795,7 +1784,7 @@
}
foreach ( $submenu[ $menu_slug ] as $i => $item ) {
- if ( $submenu_slug == $item[2] ) {
+ if ( $submenu_slug === $item[2] ) {
unset( $submenu[ $menu_slug ][ $i ] );
return $item;
}
@@ -1822,6 +1811,7 @@
if ( isset( $_parent_pages[ $menu_slug ] ) ) {
$parent_slug = $_parent_pages[ $menu_slug ];
+
if ( $parent_slug && ! isset( $_parent_pages[ $parent_slug ] ) ) {
$url = admin_url( add_query_arg( 'page', $menu_slug, $parent_slug ) );
} else {
@@ -1870,33 +1860,40 @@
if ( isset( $_wp_real_parent_file[ $parent ] ) ) {
$parent = $_wp_real_parent_file[ $parent ];
}
+
return $parent;
}
if ( 'admin.php' === $pagenow && isset( $plugin_page ) ) {
foreach ( (array) $menu as $parent_menu ) {
- if ( $parent_menu[2] == $plugin_page ) {
+ if ( $parent_menu[2] === $plugin_page ) {
$parent_file = $plugin_page;
+
if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
$parent_file = $_wp_real_parent_file[ $parent_file ];
}
+
return $parent_file;
}
}
if ( isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
$parent_file = $plugin_page;
+
if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
$parent_file = $_wp_real_parent_file[ $parent_file ];
}
+
return $parent_file;
}
}
if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $pagenow ][ $plugin_page ] ) ) {
$parent_file = $pagenow;
+
if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
$parent_file = $_wp_real_parent_file[ $parent_file ];
}
+
return $parent_file;
}
@@ -1905,13 +1902,16 @@
if ( isset( $_wp_real_parent_file[ $parent ] ) ) {
$parent = $_wp_real_parent_file[ $parent ];
}
- if ( ! empty( $typenow ) && ( "$pagenow?post_type=$typenow" === $submenu_array[2] ) ) {
+
+ if ( ! empty( $typenow ) && "$pagenow?post_type=$typenow" === $submenu_array[2] ) {
$parent_file = $parent;
return $parent;
- } elseif ( $submenu_array[2] == $pagenow && empty( $typenow ) && ( empty( $parent_file ) || false === strpos( $parent_file, '?' ) ) ) {
+ } elseif ( empty( $typenow ) && $pagenow === $submenu_array[2]
+ && ( empty( $parent_file ) || false === strpos( $parent_file, '?' ) )
+ ) {
$parent_file = $parent;
return $parent;
- } elseif ( isset( $plugin_page ) && ( $plugin_page == $submenu_array[2] ) ) {
+ } elseif ( isset( $plugin_page ) && $plugin_page === $submenu_array[2] ) {
$parent_file = $parent;
return $parent;
}
@@ -1953,10 +1953,10 @@
if ( empty( $parent ) ) {
foreach ( (array) $menu as $menu_array ) {
if ( isset( $menu_array[3] ) ) {
- if ( $menu_array[2] == $pagenow ) {
+ if ( $menu_array[2] === $pagenow ) {
$title = $menu_array[3];
return $menu_array[3];
- } elseif ( isset( $plugin_page ) && ( $plugin_page == $menu_array[2] ) && ( $hook == $menu_array[5] ) ) {
+ } elseif ( isset( $plugin_page ) && $plugin_page === $menu_array[2] && $hook === $menu_array[5] ) {
$title = $menu_array[3];
return $menu_array[3];
}
@@ -1968,21 +1968,19 @@
} else {
foreach ( array_keys( $submenu ) as $parent ) {
foreach ( $submenu[ $parent ] as $submenu_array ) {
- if ( isset( $plugin_page ) &&
- ( $plugin_page == $submenu_array[2] ) &&
- (
- ( $parent == $pagenow ) ||
- ( $parent == $plugin_page ) ||
- ( $plugin_page == $hook ) ||
- ( 'admin.php' === $pagenow && $parent1 != $submenu_array[2] ) ||
- ( ! empty( $typenow ) && $parent == $pagenow . '?post_type=' . $typenow )
- )
+ if ( isset( $plugin_page )
+ && $plugin_page === $submenu_array[2]
+ && ( $pagenow === $parent
+ || $plugin_page === $parent
+ || $plugin_page === $hook
+ || 'admin.php' === $pagenow && $parent1 !== $submenu_array[2]
+ || ! empty( $typenow ) && "$pagenow?post_type=$typenow" === $parent )
) {
$title = $submenu_array[3];
return $submenu_array[3];
}
- if ( $submenu_array[2] != $pagenow || isset( $_GET['page'] ) ) { // Not the current page.
+ if ( $submenu_array[2] !== $pagenow || isset( $_GET['page'] ) ) { // Not the current page.
continue;
}
@@ -1997,10 +1995,11 @@
}
if ( empty( $title ) ) {
foreach ( $menu as $menu_array ) {
- if ( isset( $plugin_page ) &&
- ( $plugin_page == $menu_array[2] ) &&
- ( 'admin.php' === $pagenow ) &&
- ( $parent1 == $menu_array[2] ) ) {
+ if ( isset( $plugin_page )
+ && $plugin_page === $menu_array[2]
+ && 'admin.php' === $pagenow
+ && $parent1 === $menu_array[2]
+ ) {
$title = $menu_array[3];
return $menu_array[3];
}
@@ -2113,6 +2112,7 @@
if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
return false;
}
+
foreach ( array_keys( $_wp_submenu_nopriv ) as $key ) {
if ( isset( $_wp_submenu_nopriv[ $key ][ $pagenow ] ) ) {
return false;
@@ -2121,38 +2121,27 @@
return false;
}
}
+
return true;
}
- if ( isset( $plugin_page ) && ( $plugin_page == $parent ) && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
+ if ( isset( $plugin_page ) && $plugin_page === $parent && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
return false;
}
if ( isset( $submenu[ $parent ] ) ) {
foreach ( $submenu[ $parent ] as $submenu_array ) {
- if ( isset( $plugin_page ) && ( $submenu_array[2] == $plugin_page ) ) {
- if ( current_user_can( $submenu_array[1] ) ) {
- return true;
- } else {
- return false;
- }
- } elseif ( $submenu_array[2] == $pagenow ) {
- if ( current_user_can( $submenu_array[1] ) ) {
- return true;
- } else {
- return false;
- }
+ if ( isset( $plugin_page ) && $submenu_array[2] === $plugin_page ) {
+ return current_user_can( $submenu_array[1] );
+ } elseif ( $submenu_array[2] === $pagenow ) {
+ return current_user_can( $submenu_array[1] );
}
}
}
foreach ( $menu as $menu_array ) {
- if ( $menu_array[2] == $parent ) {
- if ( current_user_can( $menu_array[1] ) ) {
- return true;
- } else {
- return false;
- }
+ if ( $menu_array[2] === $parent ) {
+ return current_user_can( $menu_array[1] );
}
}
@@ -2188,7 +2177,7 @@
/**
* Adds an array of options to the list of allowed options.
*
- * @since 2.7.0
+ * @since 5.5.0
*
* @global array $allowed_options
*
@@ -2294,7 +2283,7 @@
}
wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
- include WP_PLUGIN_DIR . '/' . $plugin;
+ include_once WP_PLUGIN_DIR . '/' . $plugin;
}
/**
@@ -2460,6 +2449,8 @@
* Renders an admin notice in case some plugins have been paused due to errors.
*
* @since 5.2.0
+ *
+ * @global string $pagenow
*/
function paused_plugins_notice() {
if ( 'plugins.php' === $GLOBALS['pagenow'] ) {
@@ -2482,3 +2473,88 @@
__( 'Go to the Plugins screen' )
);
}
+
+/**
+ * Renders an admin notice when a plugin was deactivated during an update.
+ *
+ * Displays an admin notice in case a plugin has been deactivated during an
+ * upgrade due to incompatibility with the current version of WordPress.
+ *
+ * @since 5.8.0
+ * @access private
+ *
+ * @global string $pagenow
+ * @global string $wp_version
+ */
+function deactivated_plugins_notice() {
+ if ( 'plugins.php' === $GLOBALS['pagenow'] ) {
+ return;
+ }
+
+ if ( ! current_user_can( 'activate_plugins' ) ) {
+ return;
+ }
+
+ $blog_deactivated_plugins = get_option( 'wp_force_deactivated_plugins' );
+ $site_deactivated_plugins = array();
+
+ if ( false === $blog_deactivated_plugins ) {
+ // Option not in database, add an empty array to avoid extra DB queries on subsequent loads.
+ update_option( 'wp_force_deactivated_plugins', array() );
+ }
+
+ if ( is_multisite() ) {
+ $site_deactivated_plugins = get_site_option( 'wp_force_deactivated_plugins' );
+ if ( false === $site_deactivated_plugins ) {
+ // Option not in database, add an empty array to avoid extra DB queries on subsequent loads.
+ update_site_option( 'wp_force_deactivated_plugins', array() );
+ }
+ }
+
+ if ( empty( $blog_deactivated_plugins ) && empty( $site_deactivated_plugins ) ) {
+ // No deactivated plugins.
+ return;
+ }
+
+ $deactivated_plugins = array_merge( $blog_deactivated_plugins, $site_deactivated_plugins );
+
+ foreach ( $deactivated_plugins as $plugin ) {
+ if ( ! empty( $plugin['version_compatible'] ) && ! empty( $plugin['version_deactivated'] ) ) {
+ $explanation = sprintf(
+ /* translators: 1: Name of deactivated plugin, 2: Plugin version deactivated, 3: Current WP version, 4: Compatible plugin version */
+ __( '%1$s %2$s was deactivated due to incompatibility with WordPress %3$s, please upgrade to %1$s %4$s or later.' ),
+ $plugin['plugin_name'],
+ $plugin['version_deactivated'],
+ $GLOBALS['wp_version'],
+ $plugin['version_compatible']
+ );
+ } else {
+ $explanation = sprintf(
+ /* translators: 1: Name of deactivated plugin, 2: Plugin version deactivated, 3: Current WP version */
+ __( '%1$s %2$s was deactivated due to incompatibility with WordPress %3$s.' ),
+ $plugin['plugin_name'],
+ ! empty( $plugin['version_deactivated'] ) ? $plugin['version_deactivated'] : '',
+ $GLOBALS['wp_version'],
+ $plugin['version_compatible']
+ );
+ }
+
+ printf(
+ '<div class="notice notice-warning"><p><strong>%s</strong><br>%s</p><p><a href="%s">%s</a></p></div>',
+ sprintf(
+ /* translators: %s: Name of deactivated plugin */
+ __( '%s plugin deactivated during WordPress upgrade.' ),
+ $plugin['plugin_name']
+ ),
+ $explanation,
+ esc_url( admin_url( 'plugins.php?plugin_status=inactive' ) ),
+ __( 'Go to the Plugins screen' )
+ );
+ }
+
+ // Empty the options.
+ update_option( 'wp_force_deactivated_plugins', array() );
+ if ( is_multisite() ) {
+ update_site_option( 'wp_force_deactivated_plugins', array() );
+ }
+}