Ticket #44458: 44458-2.diff
File 44458-2.diff, 16.0 KB (added by , 3 years ago) |
---|
-
src/wp-admin/css/list-tables.css
diff --git src/wp-admin/css/list-tables.css src/wp-admin/css/list-tables.css index 8d78983993..8bef97bae2 100644
ul.cat-checklist { 1301 1301 text-decoration: underline; 1302 1302 } 1303 1303 1304 .plugins tr.paused th.check-column { 1305 border-left: 4px solid #d54e21; 1306 } 1307 1308 .plugins tr.paused th, 1309 .plugins tr.paused td { 1310 background-color: #fef7f1; 1311 } 1312 1313 .plugins tr.paused .plugin-title, 1314 .plugins .paused .dashicons-warning { 1315 color: #dc3232; 1316 } 1317 1318 .plugins .resume-link { 1319 color: #dc3232; 1320 } 1321 1304 1322 .plugin-card .update-now:before { 1305 1323 color: #f56e28; 1306 1324 content: "\f463"; -
src/wp-admin/includes/admin-filters.php
diff --git src/wp-admin/includes/admin-filters.php src/wp-admin/includes/admin-filters.php index bfc9f51cfc..0686b9b8c2 100644
add_action( 'load-plugins.php', 'wp_plugin_update_rows', 20 ); // After wp_updat 119 119 add_action( 'load-themes.php', 'wp_theme_update_rows', 20 ); // After wp_update_themes() is called. 120 120 121 121 add_action( 'admin_notices', 'update_nag', 3 ); 122 add_action( 'admin_notices', 'paused_plugins_notice', 5 ); 122 123 add_action( 'admin_notices', 'maintenance_nag', 10 ); 123 124 124 125 add_filter( 'update_footer', 'core_update_footer' ); -
src/wp-admin/includes/class-wp-plugins-list-table.php
diff --git src/wp-admin/includes/class-wp-plugins-list-table.php src/wp-admin/includes/class-wp-plugins-list-table.php index 6e130f94b4..e169a8f245 100644
class WP_Plugins_List_Table extends WP_List_Table { 99 99 'upgrade' => array(), 100 100 'mustuse' => array(), 101 101 'dropins' => array(), 102 'paused' => isset( $GLOBALS['_paused_plugins'] ) ? $GLOBALS['_paused_plugins'] : array(), 102 103 ); 103 104 104 105 $screen = $this->screen; … … class WP_Plugins_List_Table extends WP_List_Table { 647 648 /* translators: %s: plugin name */ 648 649 $actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>'; 649 650 } 651 if ( current_user_can( 'resume_plugin' ) && is_plugin_paused( $plugin_file ) ) { 652 /* translators: %s: plugin name */ 653 $actions['resume'] = '<a class="resume-link" href="' . wp_nonce_url( 'plugins.php?action=resume&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'resume-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Resume execution of %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Resume execution' ) . '</a>'; 654 } 650 655 } else { 651 656 if ( current_user_can( 'activate_plugin', $plugin_file ) ) { 652 657 /* translators: %s: plugin name */ … … class WP_Plugins_List_Table extends WP_List_Table { 753 758 $class .= ' update'; 754 759 } 755 760 761 $paused = is_plugin_paused( $plugin_file ); 762 if ( $paused ) { 763 $class .= ' paused'; 764 } 765 756 766 $plugin_slug = isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_name ); 757 767 printf( 758 768 '<tr class="%s" data-slug="%s" data-plugin="%s">', … … class WP_Plugins_List_Table extends WP_List_Table { 836 846 $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); 837 847 echo implode( ' | ', $plugin_meta ); 838 848 839 echo '</div></td>'; 849 echo '</div>'; 850 851 if ( $paused ) { 852 echo sprintf( 853 '<p><span class="dashicons dashicons-warning"></span> <strong>%s</strong></p>', 854 __( 'This plugin failed to load properly and was paused within the admin backend.' ) 855 ); 856 } 857 858 echo '</td>'; 840 859 break; 841 860 default: 842 861 $classes = "$column_name column-$column_name $class"; -
src/wp-admin/includes/plugin.php
diff --git src/wp-admin/includes/plugin.php src/wp-admin/includes/plugin.php index c898fc5169..4acf694d0f 100644
function _get_dropins() { 444 444 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation 445 445 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance 446 446 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load 447 'php-error.php' => array( __( 'Custom PHP error message.' ), true ), // auto on error 448 'shutdown-handler' => array( __( 'Custom PHP shutdown handler.' ), true ), // auto on error 447 449 ); 448 450 449 451 if ( is_multisite() ) { … … function is_plugin_inactive( $plugin ) { 496 498 return ! is_plugin_active( $plugin ); 497 499 } 498 500 501 /** 502 * Determines whether a plugin is technically active but was paused while 503 * loading. 504 * 505 * For more information on this and similar theme functions, check out 506 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 507 * Conditional Tags} article in the Theme Developer Handbook. 508 * 509 * @since 5.0.0 510 * 511 * @param string $plugin Path to the plugin file relative to the plugins directory. 512 * 513 * @return bool True, if in the active plugins list. False, not in the list. 514 */ 515 function is_plugin_paused( $plugin ) { 516 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { 517 return false; 518 } 519 520 if ( ! is_plugin_active( $plugin ) || is_plugin_active_for_network( $plugin ) ) { 521 return false; 522 } 523 524 $plugin_path = WP_CONTENT_DIR . '/plugins/' . $plugin; 525 526 return in_array( $plugin_path, $GLOBALS['_paused_plugins'], true ); 527 } 528 499 529 /** 500 530 * Determines whether the plugin is active for the entire network. 501 531 * … … function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) { 693 723 continue; 694 724 } 695 725 726 // Clean up the database before deactivating the plugin. 727 if ( is_plugin_paused( $plugin ) ) { 728 resume_plugin( $plugin ); 729 } 730 696 731 $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin ); 697 732 698 733 if ( ! $silent ) { … … function delete_plugins( $plugins, $deprecated = '' ) { 887 922 uninstall_plugin( $plugin_file ); 888 923 } 889 924 925 // Clean up the database before removing the plugin. 926 if ( is_plugin_paused( $plugin_file ) ) { 927 resume_plugin( $plugin_file ); 928 } 929 890 930 /** 891 931 * Fires immediately before a plugin deletion attempt. 892 932 * … … function delete_plugins( $plugins, $deprecated = '' ) { 959 999 return true; 960 1000 } 961 1001 1002 /** 1003 * Resumes a single plugin. 1004 * 1005 * Resuming the plugin basically means removing its entry from the 1006 * `pause_on_admin` database option. 1007 * 1008 * @since 5.0.0 1009 * 1010 * @param string $plugin Single plugin to resume. 1011 * 1012 * @return bool|WP_Error True on success, false if `$plugin` was not paused, `WP_Error` on failure. 1013 */ 1014 function resume_plugin( $plugin ) { 1015 $pause_on_admin = get_option( 'pause_on_admin', array() ); 1016 1017 if ( ! array_key_exists( 'plugin', $pause_on_admin ) ) { 1018 return false; 1019 } 1020 1021 list( $plugin ) = explode( '/', $plugin ); 1022 1023 if ( ( $index = array_search( $plugin, $pause_on_admin['plugin'], true ) ) !== false ) { 1024 unset( $pause_on_admin['plugin'][ $index ] ); 1025 } 1026 1027 if ( count( $pause_on_admin['plugin'] ) === 0 ) { 1028 unset( $pause_on_admin['plugin'] ); 1029 } 1030 1031 $result = update_option( 'pause_on_admin', $pause_on_admin ); 1032 1033 if ( ! $result ) { 1034 return new WP_Error( 'could_not_resume_plugin', __( 'Could not resume execution of the plugin.' ) ); 1035 } 1036 1037 return true; 1038 } 1039 962 1040 /** 963 1041 * Validate active plugins 964 1042 * … … function wp_add_privacy_policy_content( $plugin_name, $policy_text ) { 2066 2144 2067 2145 WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); 2068 2146 } 2147 2148 /** 2149 * Renders an admin notice in case some plugins have been paused due to errors. 2150 * 2151 * @since 5.0.0 2152 * 2153 * @return void 2154 */ 2155 function paused_plugins_notice() { 2156 if ( 'plugins.php' === $GLOBALS['pagenow'] ) { 2157 return; 2158 } 2159 2160 if ( ! current_user_can( 'deactivate_plugins' ) ) { 2161 return; 2162 } 2163 2164 if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) { 2165 return; 2166 } 2167 2168 2169 echo sprintf( 2170 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p>%s</p></div>', 2171 __( 'One or more plugins failed to load properly.' ), 2172 __( 'You can find more details and make changes on the Plugins screen.' ), 2173 sprintf( 2174 '<a href="%s">%s</a>', 2175 admin_url( 'plugins.php' ), 2176 'Go to the Plugins screen' 2177 ) 2178 ); 2179 } -
src/wp-admin/plugins.php
diff --git src/wp-admin/plugins.php src/wp-admin/plugins.php index b482f474c0..b21254adc9 100644
if ( $action ) { 389 389 } 390 390 break; 391 391 392 case 'resume': 393 if ( ! current_user_can( 'resume_plugin', $plugin ) ) { 394 wp_die( __( 'Sorry, you are not allowed to resume execution of this plugin.' ) ); 395 } 396 397 if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) { 398 wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) ); 399 exit; 400 } 401 402 check_admin_referer( 'resume-plugin_' . $plugin ); 403 404 $result = resume_plugin( $plugin ); 405 406 if ( is_wp_error( $result ) ) { 407 wp_die( $result ); 408 } 409 410 wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) ); 411 exit; 412 392 413 default: 393 414 if ( isset( $_POST['checked'] ) ) { 394 415 check_admin_referer( 'bulk-plugins' ); … … elseif ( isset( $_GET['deleted'] ) ) : 532 553 <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins <strong>deactivated</strong>.' ); ?></p></div> 533 554 <?php elseif ( 'update-selected' == $action ) : ?> 534 555 <div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div> 556 <?php elseif ( isset( $_GET['resume'] ) ) : ?> 557 <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Execution of plugin <strong>resumed</strong>.' ); ?></p></div> 535 558 <?php endif; ?> 536 559 537 560 <div class="wrap"> -
src/wp-includes/capabilities.php
diff --git src/wp-includes/capabilities.php src/wp-includes/capabilities.php index 592995a120..315ae6e556 100644
function map_meta_cap( $cap, $user_id ) { 455 455 case 'deactivate_plugins': 456 456 case 'activate_plugin': 457 457 case 'deactivate_plugin': 458 case 'resume_plugin': 458 459 $caps[] = 'activate_plugins'; 459 460 if ( is_multisite() ) { 460 461 // update_, install_, and delete_ are handled above with is_super_admin(). -
src/wp-includes/load.php
diff --git src/wp-includes/load.php src/wp-includes/load.php index 81014fdde8..f4ee1a3dad 100644
function wp_get_active_and_valid_plugins() { 687 687 $plugins[] = WP_PLUGIN_DIR . '/' . $plugin; 688 688 } 689 689 } 690 691 /* 692 * Remove plugins from the list of active plugins when we're on an admin or 693 * login screen and the plugin appears in the `pause_on_admin` list. 694 */ 695 if ( 'wp-login.php' === $GLOBALS['pagenow'] 696 || ( is_admin() && ! wp_doing_ajax() ) ) { 697 $pause_on_admin = (array) get_option( 'pause_on_admin', array() ); 698 699 if ( ! array_key_exists( 'plugin', $pause_on_admin ) ) { 700 return $plugins; 701 } 702 703 foreach ( $plugins as $index => $plugin ) { 704 $parts = explode( 705 '/', 706 str_replace( WP_CONTENT_DIR . '/', '', $plugin ) 707 ); 708 709 if ( in_array( $parts[1], $pause_on_admin['plugin'], true ) ) { 710 unset( $plugins[ $index ] ); 711 // Store list of paused plugins for displaying an admin notice. 712 $GLOBALS['_paused_plugins'][] = $plugin; 713 } 714 } 715 } 716 690 717 return $plugins; 691 718 } 692 719 … … function wp_finalize_scraping_edited_file_errors( $scrape_key ) { 1250 1277 } 1251 1278 echo "\n###### wp_scraping_result_end:$scrape_key ######\n"; 1252 1279 } 1280 1281 /** 1282 * Wraps the shutdown handler function so it can be made pluggable at a later 1283 * stage. 1284 * 1285 * @since 5.0.0 1286 * 1287 * @return void 1288 */ 1289 function wp_shutdown_handler_wrapper() { 1290 if ( defined( 'WP_EXECUTION_SUCCEEDED' ) && WP_EXECUTION_SUCCEEDED ) { 1291 return; 1292 } 1293 1294 // Load the pluggable shutdown handler in case we found one. 1295 if ( function_exists( 'wp_handle_shutdown' ) ) { 1296 $stop_propagation = (bool) wp_handle_shutdown(); 1297 1298 if ( $stop_propagation ) { 1299 return; 1300 } 1301 } 1302 1303 $error = error_get_last(); 1304 1305 // No error, just skip the error handling code. 1306 if ( null === $error ) { 1307 return; 1308 } 1309 1310 /* 1311 * If the option API has not been loaded yet, we cannot persist our 1312 * discovery, so there's no point in moving forward. 1313 */ 1314 if ( ! function_exists( 'get_option' ) ) { 1315 return; 1316 } 1317 1318 // For now, we only trigger our safe mode on parse errors. 1319 if ( ! isset( $error['type'] ) || E_PARSE !== $error['type'] ) { 1320 return; 1321 } 1322 1323 try { 1324 $path = str_replace( WP_CONTENT_DIR . '/', '', $error['file'] ); 1325 1326 $parts = explode( '/', $path ); 1327 $type = rtrim( array_shift( $parts ), 's' ); 1328 $extension = array_shift( $parts ); 1329 1330 $pause_on_admin = get_option( 'pause_on_admin', array() ); 1331 1332 if ( ! array_key_exists( $type, $pause_on_admin ) ) { 1333 $pause_on_admin[ $type ] = array(); 1334 } 1335 1336 if ( ! in_array( $extension, $pause_on_admin[ $type ], true ) ) { 1337 $pause_on_admin[ $type ][] = $extension; 1338 } 1339 1340 update_option( 'pause_on_admin', $pause_on_admin ); 1341 1342 // Load custom PHP error template, if present. 1343 if ( is_readable( WP_CONTENT_DIR . '/php-error.php' ) ) { 1344 include WP_CONTENT_DIR . '/php-error.php'; 1345 die(); 1346 } 1347 1348 $message = sprintf( 1349 '<p>%s</p>', 1350 __( 'The site is experiencing technical difficulties.' ) 1351 ); 1352 1353 if ( function_exists( 'get_admin_url' ) ) { 1354 $url = get_admin_url(); 1355 $message .= sprintf( 1356 '<hr><p><em>%s <a href="%s">%s</a></em></p>', 1357 __( 'Are you the site owner?' ), 1358 $url, 1359 __( 'Log into the admin backend to fix this.' ) 1360 ); 1361 } 1362 1363 if ( function_exists( 'apply_filters' ) ) { 1364 /** 1365 * Filters the message that the default PHP error page displays. 1366 * 1367 * @since 5.0.0 1368 * 1369 * @param string $message HTML error message to display. 1370 */ 1371 $message = apply_filters( 'wp_technical_issues_display', $message ); 1372 } 1373 1374 wp_die( $message ); 1375 } catch ( Exception $exception ) { 1376 // Catch exceptions and remain silent. 1377 } 1378 } 1379 1380 /** 1381 * Registers the WordPress premature shutdown handler. 1382 * 1383 * @since 5.0.0 1384 * 1385 * @return void 1386 */ 1387 function wp_register_premature_shutdown_handler() { 1388 register_shutdown_function( 'wp_shutdown_handler_wrapper' ); 1389 } -
src/wp-settings.php
diff --git src/wp-settings.php src/wp-settings.php index eb632238f0..c633f05b1d 100644
require( ABSPATH . WPINC . '/load.php' ); 20 20 require( ABSPATH . WPINC . '/default-constants.php' ); 21 21 require_once( ABSPATH . WPINC . '/plugin.php' ); 22 22 23 // Make sure we register the premature shutdown handler as soon as possible. 24 wp_register_premature_shutdown_handler(); 25 23 26 /* 24 27 * These can't be directly globalized in version.php. When updating, 25 28 * we're including version.php from another installation and don't want … … global $blog_id; 40 43 // Set initial default constants including WP_MEMORY_LIMIT, WP_MAX_MEMORY_LIMIT, WP_DEBUG, SCRIPT_DEBUG, WP_CONTENT_DIR and WP_CACHE. 41 44 wp_initial_constants(); 42 45 46 /* 47 * Allow an optional shutdown handler to be included through a pluggable file. 48 * This file should register a function `wp_handle_shutdown( $context )` that 49 * returns a boolean value. If the return value evaluates to false, the default 50 * shutdown handler will not be executed. 51 */ 52 if ( is_readable( WP_CONTENT_DIR . '/shutdown-handler.php' ) ) { 53 include WP_CONTENT_DIR . '/shutdown-handler.php'; 54 } 55 43 56 // Check for the required PHP version and for the MySQL extension or a database drop-in. 44 57 wp_check_php_mysql_versions(); 45 58 … … if ( is_multisite() ) { 482 495 * @since 3.0.0 483 496 */ 484 497 do_action( 'wp_loaded' ); 498 499 /* 500 * Store the fact that we could successfully execute the entire WordPress 501 * lifecycle. This is used to skip the premature shutdown handler, as it cannot 502 * be unregistered. 503 */ 504 if ( ! defined( 'WP_EXECUTION_SUCCEEDED' ) ) { 505 define( 'WP_EXECUTION_SUCCEEDED', true ); 506 }