Changeset 44717
- Timestamp:
- 01/30/2019 11:00:30 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 3 deleted
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/list-tables.css
r44646 r44717 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 1329 1304 .plugin-card .update-now:before { 1330 1305 color: #f56e28; -
trunk/src/wp-admin/includes/admin-filters.php
r44647 r44717 118 118 119 119 add_action( 'admin_notices', 'update_nag', 3 ); 120 add_action( 'admin_notices', 'paused_plugins_notice', 5 );121 add_action( 'admin_notices', 'paused_themes_notice', 5 );122 120 add_action( 'admin_notices', 'maintenance_nag', 10 ); 123 121 -
trunk/src/wp-admin/includes/class-wp-plugins-list-table.php
r44541 r44717 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' , 'paused') ) ) {43 if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search' ) ) ) { 44 44 $status = $_REQUEST['plugin_status']; 45 45 } … … 100 100 'mustuse' => array(), 101 101 'dropins' => array(), 102 'paused' => array(),103 102 ); 104 103 … … 211 210 // On the non-network screen, show network-active plugins if allowed 212 211 $plugins['active'][ $plugin_file ] = $plugin_data; 213 if ( is_plugin_paused( $plugin_file ) ) {214 $plugins['paused'][ $plugin_file ] = $plugin_data;215 }216 212 } else { 217 213 // On the non-network screen, filter out network-active plugins … … 223 219 // On the network-admin screen, populate the active list with plugins that are network activated 224 220 $plugins['active'][ $plugin_file ] = $plugin_data; 225 if ( is_plugin_paused( $plugin_file ) ) {226 $plugins['paused'][ $plugin_file ] = $plugin_data;227 }228 221 } else { 229 222 if ( isset( $recently_activated[ $plugin_file ] ) ) { … … 453 446 $text = _n( 'Drop-ins <span class="count">(%s)</span>', 'Drop-ins <span class="count">(%s)</span>', $count ); 454 447 break; 455 case 'paused':456 /* translators: %s: plugin count */457 $text = _n( 'Paused <span class="count">(%s)</span>', 'Paused <span class="count">(%s)</span>', $count );458 break;459 448 case 'upgrade': 460 449 /* translators: %s: plugin count */ … … 645 634 $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>'; 646 635 } 647 if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) {648 /* translators: %s: plugin name */649 $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>';650 }651 636 } else { 652 637 if ( current_user_can( 'manage_network_plugins' ) ) { 653 638 /* translators: %s: plugin name */ 654 639 $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>'; 655 }656 if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) {657 /* translators: %s: plugin name */658 $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>';659 640 } 660 641 if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { … … 668 649 'network_active' => __( 'Network Active' ), 669 650 ); 670 if ( ! $restrict_network_only && current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) {671 /* translators: %s: plugin name */672 $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>';673 }674 651 } elseif ( $restrict_network_only ) { 675 652 $actions = array( … … 681 658 $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>'; 682 659 } 683 if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) {684 /* translators: %s: plugin name */685 $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>';686 }687 660 } else { 688 661 if ( current_user_can( 'activate_plugin', $plugin_file ) ) { … … 790 763 if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) ) { 791 764 $class .= ' update'; 792 }793 794 $paused = is_plugin_paused( $plugin_file );795 $paused_on_network_sites_count = $screen->in_admin( 'network' ) ? count_paused_plugin_sites_for_network( $plugin_file ) : 0;796 if ( $paused || $paused_on_network_sites_count ) {797 $class .= ' paused';798 765 } 799 766 … … 879 846 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 880 847 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 881 * 'Drop-ins', 'Search' , 'Paused'.848 * 'Drop-ins', 'Search'. 882 849 */ 883 850 $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); … … 885 852 886 853 echo '</div>'; 887 888 if ( $paused || $paused_on_network_sites_count ) {889 $notice_text = __( 'This plugin failed to load properly and was paused within the admin backend.' );890 if ( $screen->in_admin( 'network' ) && $paused_on_network_sites_count ) {891 $notice_text = sprintf(892 /* translators: %s: number of sites */893 _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 ),894 number_format_i18n( $paused_on_network_sites_count )895 );896 }897 898 printf( '<p><span class="dashicons dashicons-warning"></span> <strong>%s</strong></p>', $notice_text );899 900 $error = wp_get_plugin_error( $plugin_file );901 902 if ( false !== $error ) {903 $constants = get_defined_constants( true );904 $constants = isset( $constants['Core'] ) ? $constants['Core'] : $constants['internal'];905 906 foreach ( $constants as $constant => $value ) {907 if ( 0 === strpos( $constant, 'E_' ) ) {908 $core_errors[ $value ] = $constant;909 }910 }911 912 $error['type'] = $core_errors[ $error['type'] ];913 914 printf(915 '<div class="error-display"><p>%s</p></div>',916 sprintf(917 /* translators: 1: error type, 2: error line number, 3: error file name, 4: error message */918 __( 'The plugin caused an error of type %1$s in line %2$s of the file %3$s. Error message: %4$s' ),919 "<code>{$error['type']}</code>",920 "<code>{$error['line']}</code>",921 "<code>{$error['file']}</code>",922 "<code>{$error['message']}</code>"923 )924 );925 }926 }927 854 928 855 echo '</td>'; … … 959 886 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 960 887 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 961 * 'Drop-ins', 'Search' , 'Paused'.888 * 'Drop-ins', 'Search'. 962 889 */ 963 890 do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status ); … … 975 902 * @param string $status Status of the plugin. Defaults are 'All', 'Active', 976 903 * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', 977 * 'Drop-ins', 'Search' , 'Paused'.904 * 'Drop-ins', 'Search'. 978 905 */ 979 906 do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status ); -
trunk/src/wp-admin/includes/plugin.php
r44675 r44717 469 469 function _get_dropins() { 470 470 $dropins = array( 471 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE 472 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load 473 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error 474 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation 475 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance 476 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load 477 'php-error.php' => array( __( 'Custom PHP error message.' ), true ), // auto on error 478 'fatal-error-handler.php' => array( __( 'Custom PHP fatal error handler.' ), true ), // auto on error 471 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE 472 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load 473 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error 474 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation 475 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance 476 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load 479 477 ); 480 478 … … 527 525 function is_plugin_inactive( $plugin ) { 528 526 return ! is_plugin_active( $plugin ); 529 }530 531 /**532 * Determines whether a plugin is technically active but was paused while533 * loading.534 *535 * For more information on this and similar theme functions, check out536 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/537 * Conditional Tags} article in the Theme Developer Handbook.538 *539 * @since 5.1.0540 *541 * @param string $plugin Path to the plugin file relative to the plugins directory.542 * @return bool True, if in the list of paused plugins. False, not in the list.543 */544 function is_plugin_paused( $plugin ) {545 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) {546 return false;547 }548 549 if ( ! is_plugin_active( $plugin ) && ! is_plugin_active_for_network( $plugin ) ) {550 return false;551 }552 553 list( $plugin ) = explode( '/', $plugin );554 555 return array_key_exists( $plugin, $GLOBALS['_paused_plugins'] );556 }557 558 /**559 * Gets the error that was recorded for a paused plugin.560 *561 * @since 5.1.0562 *563 * @param string $plugin Path to the plugin file relative to the plugins564 * directory.565 * @return array|false Array of error information as it was returned by566 * `error_get_last()`, or false if none was recorded.567 */568 function wp_get_plugin_error( $plugin ) {569 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) {570 return false;571 }572 573 list( $plugin ) = explode( '/', $plugin );574 575 if ( ! array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ) ) {576 return false;577 }578 579 return $GLOBALS['_paused_plugins'][ $plugin ];580 }581 582 /**583 * Gets the number of sites on which a specific plugin is paused.584 *585 * @since 5.1.0586 *587 * @param string $plugin Path to the plugin file relative to the plugins directory.588 * @return int Site count.589 */590 function count_paused_plugin_sites_for_network( $plugin ) {591 if ( ! is_multisite() ) {592 return is_plugin_paused( $plugin ) ? 1 : 0;593 }594 595 list( $plugin ) = explode( '/', $plugin );596 597 $query_args = array(598 'count' => true,599 'number' => 0,600 'network_id' => get_current_network_id(),601 'meta_query' => array(602 wp_paused_plugins()->get_site_meta_query_clause( $plugin ),603 ),604 );605 606 return get_sites( $query_args );607 527 } 608 528 … … 802 722 if ( ! is_plugin_active( $plugin ) ) { 803 723 continue; 804 }805 806 // Clean up the database before deactivating the plugin.807 if ( is_plugin_paused( $plugin ) ) {808 resume_plugin( $plugin );809 724 } 810 725 … … 1003 918 } 1004 919 1005 // Clean up the database before removing the plugin.1006 if ( is_plugin_paused( $plugin_file ) ) {1007 resume_plugin( $plugin_file );1008 }1009 1010 920 /** 1011 921 * Fires immediately before a plugin deletion attempt. … … 1080 990 1081 991 return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) ); 1082 }1083 1084 return true;1085 }1086 1087 /**1088 * Tries to resume a single plugin.1089 *1090 * If a redirect was provided, we first ensure the plugin does not throw fatal1091 * errors anymore.1092 *1093 * The way it works is by setting the redirection to the error before trying to1094 * include the plugin file. If the plugin fails, then the redirection will not1095 * be overwritten with the success message and the plugin will not be resumed.1096 *1097 * @since 5.1.01098 *1099 * @param string $plugin Single plugin to resume.1100 * @param string $redirect Optional. URL to redirect to. Default empty string.1101 * @param bool $network_wide Optional. Whether to resume the plugin for the entire1102 * network. Default false.1103 * @return bool|WP_Error True on success, false if `$plugin` was not paused,1104 * `WP_Error` on failure.1105 */1106 function resume_plugin( $plugin, $redirect = '', $network_wide = false ) {1107 /*1108 * We'll override this later if the plugin could be included without1109 * creating a fatal error.1110 */1111 if ( ! empty( $redirect ) ) {1112 wp_redirect(1113 add_query_arg(1114 '_error_nonce',1115 wp_create_nonce( 'plugin-resume-error_' . $plugin ),1116 $redirect1117 )1118 );1119 1120 // Load the plugin to test whether it throws a fatal error.1121 ob_start();1122 plugin_sandbox_scrape( $plugin );1123 ob_clean();1124 }1125 1126 $result = wp_forget_extension_error( 'plugins', $plugin, $network_wide );1127 1128 if ( ! $result ) {1129 return new WP_Error(1130 'could_not_resume_plugin',1131 __( 'Could not resume the plugin.' )1132 );1133 992 } 1134 993 … … 2243 2102 WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); 2244 2103 } 2245 2246 /**2247 * Renders an admin notice in case some plugins have been paused due to errors.2248 *2249 * @since 5.1.02250 */2251 function paused_plugins_notice() {2252 if ( 'plugins.php' === $GLOBALS['pagenow'] ) {2253 return;2254 }2255 2256 if ( ! current_user_can( 'deactivate_plugins' ) ) {2257 return;2258 }2259 2260 if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) {2261 return;2262 }2263 2264 printf(2265 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p>%s</p></div>',2266 __( 'One or more plugins failed to load properly.' ),2267 __( 'You can find more details and make changes on the Plugins screen.' ),2268 sprintf(2269 '<a href="%s">%s</a>',2270 admin_url( 'plugins.php?plugin_status=paused' ),2271 'Go to the Plugins screen'2272 )2273 );2274 } -
trunk/src/wp-admin/includes/theme.php
r44675 r44717 769 769 <?php 770 770 } 771 772 /**773 * Determines whether a theme is technically active but was paused while774 * loading.775 *776 * For more information on this and similar theme functions, check out777 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/778 * Conditional Tags} article in the Theme Developer Handbook.779 *780 * @since 5.1.0781 *782 * @param string $theme Path to the theme directory relative to the themes directory.783 * @return bool True, if in the list of paused themes. False, not in the list.784 */785 function is_theme_paused( $theme ) {786 if ( ! isset( $GLOBALS['_paused_themes'] ) ) {787 return false;788 }789 790 if ( $theme !== get_stylesheet() && $theme !== get_template() ) {791 return false;792 }793 794 return array_key_exists( $theme, $GLOBALS['_paused_themes'] );795 }796 797 /**798 * Gets the error that was recorded for a paused theme.799 *800 * @since 5.1.0801 *802 * @param string $theme Path to the theme directory relative to the themes803 * directory.804 * @return array|false Array of error information as it was returned by805 * `error_get_last()`, or false if none was recorded.806 */807 function wp_get_theme_error( $theme ) {808 if ( ! isset( $GLOBALS['_paused_themes'] ) ) {809 return false;810 }811 812 if ( ! array_key_exists( $theme, $GLOBALS['_paused_themes'] ) ) {813 return false;814 }815 816 return $GLOBALS['_paused_themes'][ $theme ];817 }818 819 /**820 * Gets the number of sites on which a specific theme is paused.821 *822 * @since 5.1.0823 *824 * @param string $theme Path to the theme directory relative to the themes directory.825 * @return int Site count.826 */827 function count_paused_theme_sites_for_network( $theme ) {828 if ( ! is_multisite() ) {829 return is_theme_paused( $theme ) ? 1 : 0;830 }831 832 $query_args = array(833 'count' => true,834 'number' => 0,835 'network_id' => get_current_network_id(),836 'meta_query' => array(837 wp_paused_themes()->get_site_meta_query_clause( $theme ),838 ),839 );840 841 return get_sites( $query_args );842 }843 844 /**845 * Tries to resume a single theme.846 *847 * @since 5.1.0848 *849 * @param string $theme Single theme to resume.850 * @return bool|WP_Error True on success, false if `$theme` was not paused,851 * `WP_Error` on failure.852 */853 function resume_theme( $theme ) {854 $result = wp_forget_extension_error( 'themes', $theme );855 856 if ( ! $result ) {857 return new WP_Error(858 'could_not_resume_theme',859 __( 'Could not resume the theme.' )860 );861 }862 863 return true;864 }865 866 /**867 * Renders an admin notice in case some themes have been paused due to errors.868 *869 * @since 5.1.0870 */871 function paused_themes_notice() {872 if ( 'themes.php' === $GLOBALS['pagenow'] ) {873 return;874 }875 876 if ( ! current_user_can( 'switch_themes' ) ) {877 return;878 }879 880 if ( ! isset( $GLOBALS['_paused_themes'] ) || empty( $GLOBALS['_paused_themes'] ) ) {881 return;882 }883 884 printf(885 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p>%s</p></div>',886 __( 'One or more themes failed to load properly.' ),887 __( 'You can find more details and make changes on the Themes screen.' ),888 sprintf(889 '<a href="%s">%s</a>',890 admin_url( 'themes.php' ),891 'Go to the Themes screen'892 )893 );894 } -
trunk/src/wp-admin/plugins.php
r44524 r44717 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 413 392 default: 414 393 if ( isset( $_POST['checked'] ) ) { … … 510 489 ); 511 490 $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>.' );514 491 } else { 515 492 $errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' ); … … 565 542 <?php elseif ( 'update-selected' == $action ) : ?> 566 543 <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>569 544 <?php endif; ?> 570 545 -
trunk/src/wp-admin/themes.php
r44524 r44717 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 40345 );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' ) );55 35 exit; 56 36 } elseif ( 'delete' == $_GET['action'] ) { … … 216 196 <div id="message4" class="error"><p><?php _e( 'You cannot delete a theme while it has an active child theme.' ); ?></p></div> 217 197 <?php 218 } elseif ( isset( $_GET['resumed'] ) ) {219 ?>220 <div id="message5" class="updated notice is-dismissible"><p><?php _e( 'Theme resumed.' ); ?></p></div>221 <?php222 198 } 223 199 … … 373 349 374 350 <?php 375 $can_resume = current_user_can( 'resume_themes' );376 351 $can_delete = current_user_can( 'delete_themes' ); 377 352 $can_install = current_user_can( 'install_themes' ); … … 381 356 <th><?php _ex( 'Name', 'theme name' ); ?></th> 382 357 <th><?php _e( 'Description' ); ?></th> 383 <?php if ( $can_resume ) { ?>384 <td></td>385 <?php } ?>386 358 <?php if ( $can_delete ) { ?> 387 359 <td></td> … … 396 368 <td><?php echo $broken_theme->errors()->get_error_message(); ?></td> 397 369 <?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 <?php412 } else {413 ?>414 <td></td>415 <?php416 }417 }418 419 370 if ( $can_delete ) { 420 371 $stylesheet = $broken_theme->get_stylesheet(); -
trunk/src/wp-includes/capabilities.php
r44524 r44717 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;475 467 case 'delete_user': 476 468 case 'delete_users': -
trunk/src/wp-includes/class-wp-theme.php
r44562 r44717 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.' ) );376 372 } 377 373 -
trunk/src/wp-includes/load.php
r44566 r44717 698 698 } 699 699 700 /*701 * Remove plugins from the list of active plugins when we're on an endpoint702 * 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 708 return $plugins;709 }710 711 /**712 * Filters a given list of plugins, removing any paused plugins from it.713 *714 * @since 5.1.0715 *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 700 return $plugins; 738 701 } … … 762 725 763 726 $themes[] = TEMPLATEPATH; 764 765 /*766 * Remove themes from the list of active themes when we're on an endpoint767 * 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.0785 *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 727 807 728 return $themes; … … 1291 1212 1292 1213 /** 1293 * Determines whether we are currently on an endpoint that should be protected against WSODs.1294 *1295 * @since 5.1.01296 *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 by1319 * WordPress core. As such, it exclusively allows providing further protected endpoints in1320 * addition to the admin backend, login pages and protected AJAX actions.1321 *1322 * @since 5.1.01323 *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.01333 *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.01362 *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 /**1375 1214 * Determines whether the current request is a WordPress cron request. 1376 1215 * -
trunk/src/wp-includes/ms-load.php
r44524 r44717 52 52 $plugins[] = WP_PLUGIN_DIR . '/' . $plugin; 53 53 } 54 }55 56 /*57 * Remove plugins from the list of active plugins when we're on an endpoint58 * 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 54 } 63 55 -
trunk/src/wp-settings.php
r44692 r44717 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-fatal-error-handler.php' );22 require( ABSPATH . WPINC . '/error-protection.php' );23 20 require( ABSPATH . WPINC . '/default-constants.php' ); 24 21 require_once( ABSPATH . WPINC . '/plugin.php' ); 25 26 // Make sure we register the shutdown handler for fatal errors as soon as possible.27 wp_register_fatal_error_handler();28 22 29 23 /* … … 531 525 */ 532 526 do_action( 'wp_loaded' ); 533 534 /*535 * Store the fact that we could successfully execute the entire WordPress536 * lifecycle. This is used to skip the premature shutdown handler, as it cannot537 * be unregistered.538 */539 if ( ! defined( 'WP_EXECUTION_SUCCEEDED' ) ) {540 define( 'WP_EXECUTION_SUCCEEDED', true );541 } -
trunk/tests/phpunit/tests/user/capabilities.php
r44525 r44717 258 258 'erase_others_personal_data' => array( 'administrator' ), 259 259 'manage_privacy_options' => array( 'administrator' ), 260 'resume_themes' => array( 'administrator' ),261 260 262 261 'edit_categories' => array( 'administrator', 'editor' ), … … 298 297 'delete_site' => array( 'administrator' ), 299 298 'add_users' => array( 'administrator' ), 300 'resume_themes' => array( 'administrator' ),301 299 302 300 'edit_categories' => array( 'administrator', 'editor' ), … … 457 455 $expected['activate_plugin'], 458 456 $expected['deactivate_plugin'], 459 $expected['resume_plugin'],460 457 $expected['remove_user'], 461 458 $expected['promote_user'],
Note: See TracChangeset
for help on using the changeset viewer.