Changeset 44524
- Timestamp:
- 01/09/2019 08:04:55 PM (6 years ago)
- Location:
- trunk/src
- Files:
-
- 3 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/list-tables.css
r44352 r44524 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 .paused .error-display p, 1319 .plugins .paused .error-display code { 1320 font-size: 90%; 1321 font-style: italic; 1322 color: rgb( 0, 0, 0, 0.7 ); 1323 } 1324 1325 .plugins .resume-link { 1326 color: #dc3232; 1327 } 1328 1304 1329 .plugin-card .update-now:before { 1305 1330 color: #f56e28; -
trunk/src/wp-admin/includes/admin-filters.php
r44291 r44524 124 124 125 125 add_action( 'admin_notices', 'update_nag', 3 ); 126 add_action( 'admin_notices', 'paused_plugins_notice', 5 ); 127 add_action( 'admin_notices', 'paused_themes_notice', 5 ); 126 128 add_action( 'admin_notices', 'maintenance_nag', 10 ); 127 129 -
trunk/src/wp-admin/includes/class-wp-plugins-list-table.php
r43571 r44524 41 41 42 42 $status = 'all'; 43 if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search' ) ) ) {43 if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused' ) ) ) { 44 44 $status = $_REQUEST['plugin_status']; 45 45 } … … 100 100 'mustuse' => array(), 101 101 'dropins' => array(), 102 'paused' => array(), 102 103 ); 103 104 … … 210 211 // On the non-network screen, show network-active plugins if allowed 211 212 $plugins['active'][ $plugin_file ] = $plugin_data; 213 if ( is_plugin_paused( $plugin_file ) ) { 214 $plugins['paused'][ $plugin_file ] = $plugin_data; 215 } 212 216 } else { 213 217 // On the non-network screen, filter out network-active plugins … … 219 223 // On the network-admin screen, populate the active list with plugins that are network activated 220 224 $plugins['active'][ $plugin_file ] = $plugin_data; 225 if ( is_plugin_paused( $plugin_file ) ) { 226 $plugins['paused'][ $plugin_file ] = $plugin_data; 227 } 221 228 } else { 222 229 if ( isset( $recently_activated[ $plugin_file ] ) ) { … … 438 445 case 'dropins': 439 446 $text = _n( 'Drop-ins <span class="count">(%s)</span>', 'Drop-ins <span class="count">(%s)</span>', $count ); 447 break; 448 case 'paused': 449 /* translators: %s: plugin count */ 450 $text = _n( 'Paused <span class="count">(%s)</span>', 'Paused <span class="count">(%s)</span>', $count ); 440 451 break; 441 452 case 'upgrade': … … 626 637 $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( 'Network Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Network Deactivate' ) . '</a>'; 627 638 } 639 if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) { 640 /* translators: %s: plugin name */ 641 $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( 'Network Resume %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Network Resume' ) . '</a>'; 642 } 628 643 } else { 629 644 if ( current_user_can( 'manage_network_plugins' ) ) { 630 645 /* translators: %s: plugin name */ 631 646 $actions['activate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Network Activate' ) . '</a>'; 647 } 648 if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) { 649 /* translators: %s: plugin name */ 650 $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( 'Network Resume %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Network Resume' ) . '</a>'; 632 651 } 633 652 if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { … … 641 660 'network_active' => __( 'Network Active' ), 642 661 ); 662 if ( ! $restrict_network_only && current_user_can( 'resume_plugin' ) && is_plugin_paused( $plugin_file ) ) { 663 /* translators: %s: plugin name */ 664 $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 %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Resume' ) . '</a>'; 665 } 643 666 } elseif ( $restrict_network_only ) { 644 667 $actions = array( … … 649 672 /* translators: %s: plugin name */ 650 673 $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>'; 674 } 675 if ( current_user_can( 'resume_plugin' ) && is_plugin_paused( $plugin_file ) ) { 676 /* translators: %s: plugin name */ 677 $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 %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Resume' ) . '</a>'; 651 678 } 652 679 } else { … … 754 781 if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) ) { 755 782 $class .= ' update'; 783 } 784 785 $paused = is_plugin_paused( $plugin_file ); 786 $paused_on_network_sites_count = $screen->in_admin( 'network' ) ? count_paused_plugin_sites_for_network( $plugin_file ) : 0; 787 if ( $paused || $paused_on_network_sites_count ) { 788 $class .= ' paused'; 756 789 } 757 790 … … 834 867 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 835 868 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 836 * 'Drop-ins', 'Search' .869 * 'Drop-ins', 'Search', 'Paused'. 837 870 */ 838 871 $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); 839 872 echo implode( ' | ', $plugin_meta ); 840 873 841 echo '</div></td>'; 874 echo '</div>'; 875 876 if ( $paused || $paused_on_network_sites_count ) { 877 $notice_text = __( 'This plugin failed to load properly and was paused within the admin backend.' ); 878 if ( $screen->in_admin( 'network' ) && $paused_on_network_sites_count ) { 879 $notice_text = sprintf( 880 /* translators: %s: number of sites */ 881 _n( 'This plugin failed to load properly and was paused within the admin backend for %s site.', 'This plugin failed to load properly and was paused within the admin backend for %s sites.', $paused_on_network_sites_count ), 882 number_format_i18n( $paused_on_network_sites_count ) 883 ); 884 } 885 886 printf( '<p><span class="dashicons dashicons-warning"></span> <strong>%s</strong></p>', $notice_text ); 887 888 $error = wp_get_plugin_error( $plugin_file ); 889 890 if ( false !== $error ) { 891 $constants = get_defined_constants( true ); 892 $constants = isset( $constants['Core'] ) ? $constants['Core'] : $constants['internal']; 893 894 foreach ( $constants as $constant => $value ) { 895 if ( 0 === strpos( $constant, 'E_' ) ) { 896 $core_errors[ $value ] = $constant; 897 } 898 } 899 900 $error['type'] = $core_errors[ $error['type'] ]; 901 902 printf( 903 '<div class="error-display"><p>%s</p></div>', 904 sprintf( 905 /* translators: 1: error type, 2: error line number, 3: error file name, 4: error message */ 906 __( 'The plugin caused an error of type %1$s in line %2$s of the file %3$s. Error message: %4$s' ), 907 "<code>{$error['type']}</code>", 908 "<code>{$error['line']}</code>", 909 "<code>{$error['file']}</code>", 910 "<code>{$error['message']}</code>" 911 ) 912 ); 913 } 914 } 915 916 echo '</td>'; 842 917 break; 843 918 default: … … 872 947 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 873 948 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 874 * 'Drop-ins', 'Search' .949 * 'Drop-ins', 'Search', 'Paused'. 875 950 */ 876 951 do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status ); … … 888 963 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 889 964 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 890 * 'Drop-ins', 'Search' .965 * 'Drop-ins', 'Search', 'Paused'. 891 966 */ 892 967 do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status ); -
trunk/src/wp-admin/includes/plugin.php
r43361 r44524 439 439 function _get_dropins() { 440 440 $dropins = array( 441 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE 442 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load 443 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error 444 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation 445 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance 446 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load 441 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE 442 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load 443 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error 444 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation 445 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance 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.php' => array( __( 'Custom PHP shutdown handler.' ), true ), // auto on error 447 449 ); 448 450 … … 495 497 function is_plugin_inactive( $plugin ) { 496 498 return ! is_plugin_active( $plugin ); 499 } 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.1.0 510 * 511 * @param string $plugin Path to the plugin file relative to the plugins directory. 512 * @return bool True, if in the list of paused plugins. False, not in the list. 513 */ 514 function is_plugin_paused( $plugin ) { 515 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { 516 return false; 517 } 518 519 if ( ! is_plugin_active( $plugin ) && ! is_plugin_active_for_network( $plugin ) ) { 520 return false; 521 } 522 523 list( $plugin ) = explode( '/', $plugin ); 524 525 return array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ); 526 } 527 528 /** 529 * Gets the error that was recorded for a paused plugin. 530 * 531 * @since 5.1.0 532 * 533 * @param string $plugin Path to the plugin file relative to the plugins 534 * directory. 535 * @return array|false Array of error information as it was returned by 536 * `error_get_last()`, or false if none was recorded. 537 */ 538 function wp_get_plugin_error( $plugin ) { 539 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { 540 return false; 541 } 542 543 list( $plugin ) = explode( '/', $plugin ); 544 545 if ( ! array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ) ) { 546 return false; 547 } 548 549 return $GLOBALS['_paused_plugins'][ $plugin ]; 550 } 551 552 /** 553 * Gets the number of sites on which a specific plugin is paused. 554 * 555 * @since 5.1.0 556 * 557 * @param string $plugin Path to the plugin file relative to the plugins directory. 558 * @return int Site count. 559 */ 560 function count_paused_plugin_sites_for_network( $plugin ) { 561 if ( ! is_multisite() ) { 562 return is_plugin_paused( $plugin ) ? 1 : 0; 563 } 564 565 list( $plugin ) = explode( '/', $plugin ); 566 567 $query_args = array( 568 'count' => true, 569 'number' => 0, 570 'network_id' => get_current_network_id(), 571 'meta_query' => array( 572 wp_paused_plugins()->get_site_meta_query_clause( $plugin ), 573 ), 574 ); 575 576 return get_sites( $query_args ); 497 577 } 498 578 … … 692 772 if ( ! is_plugin_active( $plugin ) ) { 693 773 continue; 774 } 775 776 // Clean up the database before deactivating the plugin. 777 if ( is_plugin_paused( $plugin ) ) { 778 resume_plugin( $plugin ); 694 779 } 695 780 … … 888 973 } 889 974 975 // Clean up the database before removing the plugin. 976 if ( is_plugin_paused( $plugin_file ) ) { 977 resume_plugin( $plugin_file ); 978 } 979 890 980 /** 891 981 * Fires immediately before a plugin deletion attempt. … … 955 1045 956 1046 return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) ); 1047 } 1048 1049 return true; 1050 } 1051 1052 /** 1053 * Tries to resume a single plugin. 1054 * 1055 * If a redirect was provided, we first ensure the plugin does not throw fatal 1056 * errors anymore. 1057 * 1058 * The way it works is by setting the redirection to the error before trying to 1059 * include the plugin file. If the plugin fails, then the redirection will not 1060 * be overwritten with the success message and the plugin will not be resumed. 1061 * 1062 * @since 5.1.0 1063 * 1064 * @param string $plugin Single plugin to resume. 1065 * @param string $redirect Optional. URL to redirect to. Default empty string. 1066 * @param bool $network_wide Optional. Whether to resume the plugin for the entire 1067 * network. Default false. 1068 * @return bool|WP_Error True on success, false if `$plugin` was not paused, 1069 * `WP_Error` on failure. 1070 */ 1071 function resume_plugin( $plugin, $redirect = '', $network_wide = false ) { 1072 /* 1073 * We'll override this later if the plugin could be included without 1074 * creating a fatal error. 1075 */ 1076 if ( ! empty( $redirect ) ) { 1077 wp_redirect( 1078 add_query_arg( 1079 '_error_nonce', 1080 wp_create_nonce( 'plugin-resume-error_' . $plugin ), 1081 $redirect 1082 ) 1083 ); 1084 1085 // Load the plugin to test whether it throws a fatal error. 1086 ob_start(); 1087 plugin_sandbox_scrape( $plugin ); 1088 ob_clean(); 1089 } 1090 1091 $result = wp_forget_extension_error( 'plugins', $plugin, $network_wide ); 1092 1093 if ( ! $result ) { 1094 return new WP_Error( 1095 'could_not_resume_plugin', 1096 __( 'Could not resume the plugin.' ) 1097 ); 957 1098 } 958 1099 … … 2067 2208 WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); 2068 2209 } 2210 2211 /** 2212 * Renders an admin notice in case some plugins have been paused due to errors. 2213 * 2214 * @since 5.1.0 2215 */ 2216 function paused_plugins_notice() { 2217 if ( 'plugins.php' === $GLOBALS['pagenow'] ) { 2218 return; 2219 } 2220 2221 if ( ! current_user_can( 'deactivate_plugins' ) ) { 2222 return; 2223 } 2224 2225 if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) { 2226 return; 2227 } 2228 2229 printf( 2230 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p>%s</p></div>', 2231 __( 'One or more plugins failed to load properly.' ), 2232 __( 'You can find more details and make changes on the Plugins screen.' ), 2233 sprintf( 2234 '<a href="%s">%s</a>', 2235 admin_url( 'plugins.php?plugin_status=paused' ), 2236 'Go to the Plugins screen' 2237 ) 2238 ); 2239 } -
trunk/src/wp-admin/includes/theme.php
r43571 r44524 764 764 <?php 765 765 } 766 767 /** 768 * Determines whether a theme is technically active but was paused while 769 * loading. 770 * 771 * For more information on this and similar theme functions, check out 772 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 773 * Conditional Tags} article in the Theme Developer Handbook. 774 * 775 * @since 5.1.0 776 * 777 * @param string $theme Path to the theme directory relative to the themes directory. 778 * @return bool True, if in the list of paused themes. False, not in the list. 779 */ 780 function is_theme_paused( $theme ) { 781 if ( ! isset( $GLOBALS['_paused_themes'] ) ) { 782 return false; 783 } 784 785 if ( $theme !== get_stylesheet() && $theme !== get_template() ) { 786 return false; 787 } 788 789 return array_key_exists( $theme, $GLOBALS['_paused_themes'] ); 790 } 791 792 /** 793 * Gets the error that was recorded for a paused theme. 794 * 795 * @since 5.1.0 796 * 797 * @param string $theme Path to the theme directory relative to the themes 798 * directory. 799 * @return array|false Array of error information as it was returned by 800 * `error_get_last()`, or false if none was recorded. 801 */ 802 function wp_get_theme_error( $theme ) { 803 if ( ! isset( $GLOBALS['_paused_themes'] ) ) { 804 return false; 805 } 806 807 if ( ! array_key_exists( $theme, $GLOBALS['_paused_themes'] ) ) { 808 return false; 809 } 810 811 return $GLOBALS['_paused_themes'][ $theme ]; 812 } 813 814 /** 815 * Gets the number of sites on which a specific theme is paused. 816 * 817 * @since 5.1.0 818 * 819 * @param string $theme Path to the theme directory relative to the themes directory. 820 * @return int Site count. 821 */ 822 function count_paused_theme_sites_for_network( $theme ) { 823 if ( ! is_multisite() ) { 824 return is_theme_paused( $theme ) ? 1 : 0; 825 } 826 827 $query_args = array( 828 'count' => true, 829 'number' => 0, 830 'network_id' => get_current_network_id(), 831 'meta_query' => array( 832 wp_paused_themes()->get_site_meta_query_clause( $theme ), 833 ), 834 ); 835 836 return get_sites( $query_args ); 837 } 838 839 /** 840 * Tries to resume a single theme. 841 * 842 * @since 5.1.0 843 * 844 * @param string $theme Single theme to resume. 845 * @return bool|WP_Error True on success, false if `$theme` was not paused, 846 * `WP_Error` on failure. 847 */ 848 function resume_theme( $theme ) { 849 $result = wp_forget_extension_error( 'themes', $theme ); 850 851 if ( ! $result ) { 852 return new WP_Error( 853 'could_not_resume_theme', 854 __( 'Could not resume the theme.' ) 855 ); 856 } 857 858 return true; 859 } 860 861 /** 862 * Renders an admin notice in case some themes have been paused due to errors. 863 * 864 * @since 5.1.0 865 */ 866 function paused_themes_notice() { 867 if ( 'themes.php' === $GLOBALS['pagenow'] ) { 868 return; 869 } 870 871 if ( ! current_user_can( 'switch_themes' ) ) { 872 return; 873 } 874 875 if ( ! isset( $GLOBALS['_paused_themes'] ) || empty( $GLOBALS['_paused_themes'] ) ) { 876 return; 877 } 878 879 printf( 880 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p>%s</p></div>', 881 __( 'One or more themes failed to load properly.' ), 882 __( 'You can find more details and make changes on the Themes screen.' ), 883 sprintf( 884 '<a href="%s">%s</a>', 885 admin_url( 'themes.php' ), 886 'Go to the Themes screen' 887 ) 888 ); 889 } -
trunk/src/wp-admin/plugins.php
r43667 r44524 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 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, self_admin_url( 'plugins.php?error=resuming' ), is_network_admin() ); 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'] ) ) { … … 489 510 ); 490 511 $errmsg .= ' ' . __( 'If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.' ); 512 } elseif ( 'resuming' === $_GET['error'] ) { 513 $errmsg = __( 'Plugin could not be resumed because it triggered a <strong>fatal error</strong>.' ); 491 514 } else { 492 515 $errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' ); … … 542 565 <?php elseif ( 'update-selected' == $action ) : ?> 543 566 <div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div> 567 <?php elseif ( isset( $_GET['resume'] ) ) : ?> 568 <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin <strong>resumed</strong>.' ); ?></p></div> 544 569 <?php endif; ?> 545 570 -
trunk/src/wp-admin/themes.php
r43571 r44524 33 33 switch_theme( $theme->get_stylesheet() ); 34 34 wp_redirect( admin_url( 'themes.php?activated=true' ) ); 35 exit; 36 } elseif ( 'resume' === $_GET['action'] ) { 37 check_admin_referer( 'resume-theme_' . $_GET['stylesheet'] ); 38 $theme = wp_get_theme( $_GET['stylesheet'] ); 39 40 if ( ! current_user_can( 'resume_themes' ) ) { 41 wp_die( 42 '<h1>' . __( 'You need a higher level of permission.' ) . '</h1>' . 43 '<p>' . __( 'Sorry, you are not allowed to resume this theme.' ) . '</p>', 44 403 45 ); 46 } 47 48 $result = resume_theme( $theme->get_stylesheet() ); 49 50 if ( is_wp_error( $result ) ) { 51 wp_die( $result ); 52 } 53 54 wp_redirect( admin_url( 'themes.php?resumed=true' ) ); 35 55 exit; 36 56 } elseif ( 'delete' == $_GET['action'] ) { … … 174 194 <hr class="wp-header-end"> 175 195 <?php 176 if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) :196 if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) { 177 197 ?> 178 <div id="message1" class="updated notice is-dismissible"><p><?php _e( 'The active theme is broken. Reverting to the default theme.' ); ?></p></div>198 <div id="message1" class="updated notice is-dismissible"><p><?php _e( 'The active theme is broken. Reverting to the default theme.' ); ?></p></div> 179 199 <?php 180 elseif ( isset( $_GET['activated'] ) ) : 200 } elseif ( isset( $_GET['activated'] ) ) { 181 201 if ( isset( $_GET['previewed'] ) ) { 182 202 ?> 183 203 <div id="message2" class="updated notice is-dismissible"><p><?php _e( 'Settings saved and theme activated.' ); ?> <a href="<?php echo home_url( '/' ); ?>"><?php _e( 'Visit site' ); ?></a></p></div> 184 <?php } else { ?> 185 <div id="message2" class="updated notice is-dismissible"><p><?php _e( 'New theme activated.' ); ?> <a href="<?php echo home_url( '/' ); ?>"><?php _e( 'Visit site' ); ?></a></p></div> 186 <?php 187 } 188 elseif ( isset( $_GET['deleted'] ) ) : 204 <?php 205 } else { 189 206 ?> 190 <div id="message3" class="updated notice is-dismissible"><p><?php _e( 'Theme deleted.' ); ?></p></div> 191 <?php elseif ( isset( $_GET['delete-active-child'] ) ) : ?> 207 <div id="message2" class="updated notice is-dismissible"><p><?php _e( 'New theme activated.' ); ?> <a href="<?php echo home_url( '/' ); ?>"><?php _e( 'Visit site' ); ?></a></p></div> 208 <?php 209 } 210 } elseif ( isset( $_GET['deleted'] ) ) { 211 ?> 212 <div id="message3" class="updated notice is-dismissible"><p><?php _e( 'Theme deleted.' ); ?></p></div> 213 <?php 214 } elseif ( isset( $_GET['delete-active-child'] ) ) { 215 ?> 192 216 <div id="message4" class="error"><p><?php _e( 'You cannot delete a theme while it has an active child theme.' ); ?></p></div> 193 217 <?php 194 endif; 218 } elseif ( isset( $_GET['resumed'] ) ) { 219 ?> 220 <div id="message5" class="updated notice is-dismissible"><p><?php _e( 'Theme resumed.' ); ?></p></div> 221 <?php 222 } 195 223 196 224 $ct = wp_get_theme(); … … 345 373 346 374 <?php 375 $can_resume = current_user_can( 'resume_themes' ); 347 376 $can_delete = current_user_can( 'delete_themes' ); 348 377 $can_install = current_user_can( 'install_themes' ); … … 352 381 <th><?php _ex( 'Name', 'theme name' ); ?></th> 353 382 <th><?php _e( 'Description' ); ?></th> 383 <?php if ( $can_resume ) { ?> 384 <td></td> 385 <?php } ?> 354 386 <?php if ( $can_delete ) { ?> 355 387 <td></td> … … 364 396 <td><?php echo $broken_theme->errors()->get_error_message(); ?></td> 365 397 <?php 398 if ( $can_resume ) { 399 if ( 'theme_paused' === $broken_theme->errors()->get_error_code() ) { 400 $stylesheet = $broken_theme->get_stylesheet(); 401 $resume_url = add_query_arg( 402 array( 403 'action' => 'resume', 404 'stylesheet' => urlencode( $stylesheet ), 405 ), 406 admin_url( 'themes.php' ) 407 ); 408 $resume_url = wp_nonce_url( $resume_url, 'resume-theme_' . $stylesheet ); 409 ?> 410 <td><a href="<?php echo esc_url( $resume_url ); ?>" class="button resume-theme"><?php _e( 'Resume' ); ?></a></td> 411 <?php 412 } else { 413 ?> 414 <td></td> 415 <?php 416 } 417 } 418 366 419 if ( $can_delete ) { 367 420 $stylesheet = $broken_theme->get_stylesheet(); -
trunk/src/wp-includes/capabilities.php
r44146 r44524 465 465 } 466 466 break; 467 case 'resume_plugin': 468 // Even in a multisite, regular administrators should be able to resume a plugin. 469 $caps[] = 'activate_plugins'; 470 break; 471 case 'resume_themes': 472 // Even in a multisite, regular administrators should be able to resume a theme. 473 $caps[] = 'switch_themes'; 474 break; 467 475 case 'delete_user': 468 476 case 'delete_users': -
trunk/src/wp-includes/class-wp-theme.php
r44151 r44524 370 370 // Set the parent. Pass the current instance so we can do the crazy checks above and assess errors. 371 371 $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this ); 372 } 373 374 if ( wp_paused_themes()->get( $this->stylesheet ) && ( ! is_wp_error( $this->errors ) || ! isset( $this->errors->errors['theme_paused'] ) ) ) { 375 $this->errors = new WP_Error( 'theme_paused', __( 'This theme failed to load properly and was paused within the admin backend.' ) ); 372 376 } 373 377 -
trunk/src/wp-includes/load.php
r44453 r44524 697 697 } 698 698 } 699 700 /* 701 * Remove plugins from the list of active plugins when we're on an endpoint 702 * that should be protected against WSODs and the plugin is paused. 703 */ 704 if ( is_protected_endpoint() ) { 705 $plugins = wp_skip_paused_plugins( $plugins ); 706 } 707 699 708 return $plugins; 709 } 710 711 /** 712 * Filters a given list of plugins, removing any paused plugins from it. 713 * 714 * @since 5.1.0 715 * 716 * @param array $plugins List of absolute plugin main file paths. 717 * @return array Filtered value of $plugins, without any paused plugins. 718 */ 719 function wp_skip_paused_plugins( array $plugins ) { 720 $paused_plugins = wp_paused_plugins()->get_all(); 721 722 if ( empty( $paused_plugins ) ) { 723 return $plugins; 724 } 725 726 foreach ( $plugins as $index => $plugin ) { 727 list( $plugin ) = explode( '/', plugin_basename( $plugin ) ); 728 729 if ( array_key_exists( $plugin, $paused_plugins ) ) { 730 unset( $plugins[ $index ] ); 731 732 // Store list of paused plugins for displaying an admin notice. 733 $GLOBALS['_paused_plugins'][ $plugin ] = $paused_plugins[ $plugin ]; 734 } 735 } 736 737 return $plugins; 738 } 739 740 /** 741 * Retrieves an array of active and valid themes. 742 * 743 * While upgrading or installing WordPress, no themes are returned. 744 * 745 * @since 5.1.0 746 * @access private 747 * 748 * @return array Array of paths to theme directories. 749 */ 750 function wp_get_active_and_valid_themes() { 751 global $pagenow; 752 753 $themes = array(); 754 755 if ( wp_installing() && 'wp-activate.php' !== $pagenow ) { 756 return $themes; 757 } 758 759 if ( TEMPLATEPATH !== STYLESHEETPATH ) { 760 $themes[] = STYLESHEETPATH; 761 } 762 763 $themes[] = TEMPLATEPATH; 764 765 /* 766 * Remove themes from the list of active themes when we're on an endpoint 767 * that should be protected against WSODs and the theme is paused. 768 */ 769 if ( is_protected_endpoint() ) { 770 $themes = wp_skip_paused_themes( $themes ); 771 772 // If no active and valid themes exist, skip loading themes. 773 if ( empty( $themes ) ) { 774 add_filter( 'wp_using_themes', '__return_false' ); 775 } 776 } 777 778 return $themes; 779 } 780 781 /** 782 * Filters a given list of themes, removing any paused themes from it. 783 * 784 * @since 5.1.0 785 * 786 * @param array $themes List of absolute theme directory paths. 787 * @return array Filtered value of $themes, without any paused themes. 788 */ 789 function wp_skip_paused_themes( array $themes ) { 790 $paused_themes = wp_paused_themes()->get_all(); 791 792 if ( empty( $paused_themes ) ) { 793 return $themes; 794 } 795 796 foreach ( $themes as $index => $theme ) { 797 $theme = basename( $theme ); 798 799 if ( array_key_exists( $theme, $paused_themes ) ) { 800 unset( $themes[ $index ] ); 801 802 // Store list of paused themes for displaying an admin notice. 803 $GLOBALS['_paused_themes'][ $theme ] = $paused_themes[ $theme ]; 804 } 805 } 806 807 return $themes; 700 808 } 701 809 … … 1165 1273 1166 1274 /** 1275 * Determines whether the current request should use themes. 1276 * 1277 * @since 5.1.0 1278 * 1279 * @return bool True if themes should be used, false otherwise. 1280 */ 1281 function wp_using_themes() { 1282 /** 1283 * Filters whether the current request should use themes. 1284 * 1285 * @since 5.1.0 1286 * 1287 * @param bool $wp_using_themes Whether the current request should use themes. 1288 */ 1289 return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES ); 1290 } 1291 1292 /** 1293 * Determines whether we are currently on an endpoint that should be protected against WSODs. 1294 * 1295 * @since 5.1.0 1296 * 1297 * @return bool True if the current endpoint should be protected. 1298 */ 1299 function is_protected_endpoint() { 1300 // Protect login pages. 1301 if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) { 1302 return true; 1303 } 1304 1305 // Protect the admin backend. 1306 if ( is_admin() && ! wp_doing_ajax() ) { 1307 return true; 1308 } 1309 1310 // Protect AJAX actions that could help resolve a fatal error should be available. 1311 if ( is_protected_ajax_action() ) { 1312 return true; 1313 } 1314 1315 /** 1316 * Filters whether the current request is against a protected endpoint. 1317 * 1318 * This filter is only fired when an endpoint is requested which is not already protected by 1319 * WordPress core. As such, it exclusively allows providing further protected endpoints in 1320 * addition to the admin backend, login pages and protected AJAX actions. 1321 * 1322 * @since 5.1.0 1323 * 1324 * @param bool $is_protected_endpoint Whether the currently requested endpoint is protected. Default false. 1325 */ 1326 return (bool) apply_filters( 'is_protected_endpoint', false ); 1327 } 1328 1329 /** 1330 * Determines whether we are currently handling an AJAX action that should be protected against WSODs. 1331 * 1332 * @since 5.1.0 1333 * 1334 * @return bool True if the current AJAX action should be protected. 1335 */ 1336 function is_protected_ajax_action() { 1337 if ( ! wp_doing_ajax() ) { 1338 return false; 1339 } 1340 1341 if ( ! isset( $_REQUEST['action'] ) ) { 1342 return false; 1343 } 1344 1345 $actions_to_protect = array( 1346 'edit-theme-plugin-file', // Saving changes in the core code editor. 1347 'heartbeat', // Keep the heart beating. 1348 'install-plugin', // Installing a new plugin. 1349 'install-theme', // Installing a new theme. 1350 'search-plugins', // Searching in the list of plugins. 1351 'search-install-plugins', // Searching for a plugin in the plugin install screen. 1352 'update-plugin', // Update an existing plugin. 1353 'update-theme', // Update an existing theme. 1354 ); 1355 1356 /** 1357 * Filters the array of protected AJAX actions. 1358 * 1359 * This filter is only fired when doing AJAX and the AJAX request has an 'action' property. 1360 * 1361 * @since 5.1.0 1362 * 1363 * @param array $actions_to_protect Array of strings with AJAX actions to protect. 1364 */ 1365 $actions_to_protect = (array) apply_filters( 'wp_protected_ajax_actions', $actions_to_protect ); 1366 1367 if ( ! in_array( $_REQUEST['action'], $actions_to_protect, true ) ) { 1368 return false; 1369 } 1370 1371 return true; 1372 } 1373 1374 /** 1167 1375 * Determines whether the current request is a WordPress cron request. 1168 1376 * -
trunk/src/wp-includes/ms-load.php
r42698 r44524 53 53 } 54 54 } 55 56 /* 57 * Remove plugins from the list of active plugins when we're on an endpoint 58 * that should be protected against WSODs and the plugin is paused. 59 */ 60 if ( is_protected_endpoint() ) { 61 $plugins = wp_skip_paused_plugins( $plugins ); 62 } 63 55 64 return $plugins; 56 65 } -
trunk/src/wp-includes/template-loader.php
r42343 r44524 5 5 * @package WordPress 6 6 */ 7 if ( defined( 'WP_USE_THEMES' ) && WP_USE_THEMES) {7 if ( wp_using_themes() ) { 8 8 /** 9 9 * Fires before determining which template to load. … … 45 45 endif; 46 46 47 if ( defined( 'WP_USE_THEMES' ) && WP_USE_THEMES) :47 if ( wp_using_themes() ) : 48 48 $template = false; 49 49 if ( is_embed() && $template = get_embed_template() ) : -
trunk/src/wp-settings.php
r44344 r44524 18 18 // Include files required for initialization. 19 19 require( ABSPATH . WPINC . '/load.php' ); 20 require( ABSPATH . WPINC . '/class-wp-paused-extensions-storage.php' ); 21 require( ABSPATH . WPINC . '/class-wp-shutdown-handler.php' ); 22 require( ABSPATH . WPINC . '/error-protection.php' ); 20 23 require( ABSPATH . WPINC . '/default-constants.php' ); 21 24 require_once( ABSPATH . WPINC . '/plugin.php' ); 25 26 // Make sure we register the premature shutdown handler as soon as possible. 27 wp_register_premature_shutdown_handler(); 22 28 23 29 /* … … 475 481 476 482 // Load the functions for the active theme, for both parent and child theme if applicable. 477 if ( ! wp_installing() || 'wp-activate.php' === $pagenow) {478 if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH. '/functions.php' ) ) {479 include ( STYLESHEETPATH . '/functions.php' );483 foreach ( wp_get_active_and_valid_themes() as $theme ) { 484 if ( file_exists( $theme . '/functions.php' ) ) { 485 include $theme . '/functions.php'; 480 486 } 481 if ( file_exists( TEMPLATEPATH . '/functions.php' ) ) { 482 include( TEMPLATEPATH . '/functions.php' ); 483 } 484 } 487 } 488 unset( $theme ); 485 489 486 490 /** … … 527 531 */ 528 532 do_action( 'wp_loaded' ); 533 534 /* 535 * Store the fact that we could successfully execute the entire WordPress 536 * lifecycle. This is used to skip the premature shutdown handler, as it cannot 537 * be unregistered. 538 */ 539 if ( ! defined( 'WP_EXECUTION_SUCCEEDED' ) ) { 540 define( 'WP_EXECUTION_SUCCEEDED', true ); 541 }
Note: See TracChangeset
for help on using the changeset viewer.