From: Edward Z. Yang Semantic Personal Publishing Platform
-
Version 4.5.3
+
Version 4.6
System Requirements
-
Recommendations
-
@@ -83,7 +83,7 @@
Final Notes
Share the Love
diff --git a/wp-activate.php b/wp-activate.php
index bfd56207..0f6181a5 100644
--- a/wp-activate.php
+++ b/wp-activate.php
@@ -32,13 +32,17 @@ $wp_query->is_404 = false;
do_action( 'activate_header' );
/**
- * Adds an action hook specific to this page that fires on wp_head
+ * Adds an action hook specific to this page.
+ *
+ * Fires on {@see 'wp_head'}.
*
* @since MU
*/
function do_activate_header() {
- /**
- * Fires before the Site Activation page is loaded, but on the wp_head action.
+ /**
+ * Fires before the Site Activation page is loaded.
+ *
+ * Fires on the {@see 'wp_head'} action.
*
* @since 3.0.0
*/
@@ -88,22 +92,37 @@ get_header( 'wp-activate' );
$result = wpmu_activate_signup( $key );
if ( is_wp_error($result) ) {
if ( 'already_active' == $result->get_error_code() || 'blog_taken' == $result->get_error_code() ) {
- $signup = $result->get_error_data();
+ $signup = $result->get_error_data();
?>
';
if ( $signup->domain . $signup->path == '' ) {
- printf( __('Your account has been activated. You may now log in to the site using your chosen username of “%2$s”. Please check your email inbox at %3$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.'), network_site_url( 'wp-login.php', 'login' ), $signup->user_login, $signup->user_email, wp_lostpassword_url() );
+ printf(
+ /* translators: 1: login URL, 2: username, 3: user email, 4: lost password URL */
+ __( 'Your account has been activated. You may now log in to the site using your chosen username of “%2$s”. Please check your email inbox at %3$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.' ),
+ network_site_url( 'wp-login.php', 'login' ),
+ $signup->user_login,
+ $signup->user_email,
+ wp_lostpassword_url()
+ );
} else {
- printf( __('Your site at %2$s is active. You may now log in to your site using your chosen username of “%3$s”. Please check your email inbox at %4$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.'), 'http://' . $signup->domain, $signup->domain, $signup->user_login, $signup->user_email, wp_lostpassword_url() );
+ printf(
+ /* translators: 1: site URL, 2: site domain, 3: username, 4: user email, 5: lost password URL */
+ __( 'Your site at %2$s is active. You may now log in to your site using your chosen username of “%3$s”. Please check your email inbox at %4$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.' ),
+ 'http://' . $signup->domain,
+ $signup->domain,
+ $signup->user_login,
+ $signup->user_email,
+ wp_lostpassword_url()
+ );
}
echo '
get_error_message(); ?>
'.$result->get_error_message().''; } } else { $url = isset( $result['blog_id'] ) ? get_blogaddress_by_id( (int) $result['blog_id'] ) : ''; @@ -121,9 +140,15 @@ get_header( 'wp-activate' ); $login_url = wp_login_url(); restore_current_blog(); ?> -View your site or Log in' ), $url, esc_url( $login_url ) ); ?>
+View your site or Log in' ), $url, esc_url( $login_url ) ); + ?>
-Log in or go back to the homepage.' ), network_site_url('wp-login.php', 'login'), network_home_url() ); ?>
+Log in or go back to the homepage.' ), network_site_url( 'wp-login.php', 'login' ), network_home_url() ); + ?>
includes_url( 'js/mediaelement/', 'relative' ), + 'pauseOtherPlayers' => '', + ) ); } -$video_url = 'https://videopress.com/embed/scFdjVo6?hd=true'; +/** + * Replaces the height and width attributes with values for full size. + * + * wp_video_shortcode() limits the width to 640px. + * + * @since 4.6.0 + * @ignore + * + * @param $output Video shortcode HTML output. + * @return string Filtered HTML content to display video. + */ +function _wp_override_admin_video_width_limit( $output ) { + return str_replace( array( '640', '384' ), array( '1050', '630' ), $output ); +} + +$video_url = 'https://videopress.com/embed/GbdhpGF3?hd=true'; $locale = str_replace( '_', '-', get_locale() ); list( $locale ) = explode( '-', $locale ); if ( 'en' !== $locale ) { @@ -29,7 +49,7 @@ include( ABSPATH . 'wp-admin/admin-header.php' );Version %s addressed some security issues and fixed %2$s bug.', - 'Version %s addressed some security issues and fixed %2$s bugs.', 17 ), '4.5.3', number_format_i18n( 17 ) ); ?> - the release notes.' ), 'https://codex.wordpress.org/Version_4.5.3' ); ?> -
-Version %s addressed some security issues.' ), '4.5.2' ); ?> - the release notes.' ), 'https://codex.wordpress.org/Version_4.5.2' ); ?> -
-Version %1$s addressed %2$s bug.', - 'Version %1$s addressed %2$s bugs.', 12 ), '4.5.1', number_format_i18n( 12 ) ); ?> - the release notes.' ), 'https://codex.wordpress.org/Version_4.5.1' ); ?> -
-<code>.' ); ?>
-- customizer.' ), - esc_url( $customize_url ) - ); - } else { - _e( 'Preview mobile, tablet, and desktop views directly in the customizer.' ); - } + +
+- Site Identity section of the customizer.' ), - esc_url( add_query_arg( array( 'autofocus' => array( 'section' => 'title_tagline' ) ), $customize_url ) ) - ); - } else { - _e( 'The Twenty Fifteen and Twenty Sixteen themes have been updated to support custom logos, which can be found in the Site Identity section of the customizer.' ); - } - ?>
+ + +comprehensive framework for rendering parts of the preview without rewriting your PHP code in JavaScript.' ), - 'https://make.wordpress.org/core/2016/02/16/selective-refresh-in-the-customizer/' + /* translators: %s: https://make.wordpress.org/core/2016/07/06/resource-hints-in-4-6/ */ + __( 'Resource hints help browsers decide which resources to fetch and preprocess. WordPress 4.6 adds them automatically for your styles and scripts making your site even faster.' ), + 'https://make.wordpress.org/core/2016/07/06/resource-hints-in-4-6/' ); - if ( current_user_can( 'customize' ) && current_user_can( 'edit_theme_options' ) ) { - if ( current_theme_supports( 'menus' ) && ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { - printf( - /* translators: %s: URL to Menus section of the customizer */ - ' ' . __( 'See it in action with Menus.' ), - esc_url( add_query_arg( array( 'autofocus' => array( 'panel' => 'nav_menus' ) ), $customize_url ) ) - ); - } elseif ( current_theme_supports( 'customize-selective-refresh-widgets' ) ) { // If widgets are supported, menus are also because of the menus widget. - printf( - /* translators: 1: URL to Menus section of the customizer, 2: URL to Widgets section of the customizer */ - ' ' . __( 'See it in action with Menus or Widgets.' ), - esc_url( add_query_arg( array( 'autofocus' => array( 'panel' => 'nav_menus' ) ), $customize_url ) ), - esc_url( add_query_arg( array( 'autofocus' => array( 'panel' => 'widgets' ) ), $customize_url ) ) - ); - } - } ?>
WP_Post_Type
' );
+ ?>It’s really cool.' ),
- 'https://make.wordpress.org/core/2016/03/12/performance-improvements-for-images-in-wordpress-4-5/'
+ /* translators: 1: WP_Term_Query, 2: WP_Post_Type */
+ __( 'A new %1$s class adds flexibility to query term information while a new %2$s object makes interacting with post types more predictable.' ),
+ 'WP_Term_Query
',
+ 'WP_Post_Type
'
);
?>
wp_add_inline_script()' + /* translators: %s: https://make.wordpress.org/core/2016/07/08/enhancing-register_meta-in-4-6/ */ + __( 'The Meta Registration API has been expanded to support types, descriptions, and REST API visibility.' ), + 'https://make.wordpress.org/core/2016/07/08/enhancing-register_meta-in-4-6/' ); ?>
WordPress.org’s community of translators.' ); ?>
+API for enforcing validation constraints. Likewise, customizer controls now support notifications, which are used to display validation errors instead of failing silently.' ); ?>
+directly overridden by themes via the template hierarchy.' ),
- 'https://make.wordpress.org/core/2016/03/11/embeds-changes-in-wordpress-4-5/'
+ /* translators: 1: WP_Site_Query, 2: WP_Network_Query */
+ __( 'Cached and comprehensive site queries improve your network admin experience. The addition of %1$s and %2$s help craft advanced queries with less effort.' ),
+ 'WP_Site_Query
',
+ 'WP_Network_Query
'
);
?>
' . __( 'You are not allowed to customize the appearance of this site.' ) . '
', + '' . __( 'Sorry, you are not allowed to customize this site.' ) . '
', 403 ); } @@ -118,12 +118,12 @@ do_action( 'customize_controls_print_scripts' ); submit_button( $save_text, 'primary save', 'save', false ); ?> - + + - + @@ -134,7 +134,7 @@ do_action( 'customize_controls_print_scripts' ); ' . get_bloginfo( 'name' ) . '' ); ?> - +' . __( 'You are not allowed to edit comments.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit comments.' ) . '
', 403 ); } @@ -210,7 +210,7 @@ if ( isset( $_REQUEST['error'] ) ) { $error_msg = __( 'Invalid comment ID.' ); break; case 2 : - $error_msg = __( 'You are not allowed to edit comments on this post.' ); + $error_msg = __( 'Sorry, you are not allowed to edit comments on this post.' ); break; } if ( $error_msg ) diff --git a/wp-admin/edit-form-advanced.php b/wp-admin/edit-form-advanced.php index ea5428fe..bd229b90 100644 --- a/wp-admin/edit-form-advanced.php +++ b/wp-admin/edit-form-advanced.php @@ -11,9 +11,9 @@ if ( !defined('ABSPATH') ) die('-1'); /** - * @global string $post_type - * @global object $post_type_object - * @global WP_Post $post + * @global string $post_type + * @global WP_Post_Type $post_type_object + * @global WP_Post $post */ global $post_type, $post_type_object, $post; @@ -21,7 +21,7 @@ wp_enqueue_script('post'); $_wp_editor_expand = $_content_editor_dfw = false; /** - * Filter whether to enable the 'expand' functionality in the post editor. + * Filters whether to enable the 'expand' functionality in the post editor. * * @since 4.0.0 * @since 4.1.0 Added the `$post_type` parameter. @@ -129,7 +129,7 @@ if ( $viewable ) { } -/* translators: Publish box date format, see http://php.net/date */ +/* translators: Publish box date format, see https://secure.php.net/date */ $scheduled_date = date_i18n( __( 'M j, Y @ H:i' ), strtotime( $post->post_date ) ); $messages['post'] = array( @@ -163,7 +163,7 @@ $messages['page'] = array( $messages['attachment'] = array_fill( 1, 10, __( 'Media file updated.' ) ); // Hack, for now. /** - * Filter the post updated messages. + * Filters the post updated messages. * * @since 3.0.0 * @@ -219,7 +219,7 @@ $publish_callback_args = null; if ( post_type_supports($post_type, 'revisions') && 'auto-draft' != $post->post_status ) { $revisions = wp_get_post_revisions( $post_ID ); - // We should aim to show the revisions metabox only when there are revisions. + // We should aim to show the revisions meta box only when there are revisions. if ( count( $revisions ) > 1 ) { reset( $revisions ); // Reset pointer for key() $publish_callback_args = array( 'revisions_count' => count( $revisions ), 'revision_id' => key( $revisions ) ); @@ -543,7 +543,7 @@ do_action( 'edit_form_top', $post ); ?>' . __( 'You are not allowed to manage these items.' ) . '
', + '' . __( 'Sorry, you are not allowed to manage these items.' ) . '
', 403 ); } @@ -71,7 +71,7 @@ case 'add-tag': if ( ! current_user_can( $tax->cap->edit_terms ) ) { wp_die( '' . __( 'You are not allowed to add this item.' ) . '
', + '' . __( 'Sorry, you are not allowed to add this item.' ) . '
', 403 ); } @@ -111,7 +111,7 @@ case 'delete': if ( ! current_user_can( $tax->cap->delete_terms ) ) { wp_die( '' . __( 'You are not allowed to delete this item.' ) . '
', + '' . __( 'Sorry, you are not allowed to delete this item.' ) . '
', 403 ); } @@ -128,7 +128,7 @@ case 'bulk-delete': if ( ! current_user_can( $tax->cap->delete_terms ) ) { wp_die( '' . __( 'You are not allowed to delete these items.' ) . '
', + '' . __( 'Sorry, you are not allowed to delete these items.' ) . '
', 403 ); } @@ -171,7 +171,7 @@ case 'editedtag': if ( ! current_user_can( $tax->cap->edit_terms ) ) { wp_die( '' . __( 'You are not allowed to edit this item.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit this item.' ) . '
', 403 ); } @@ -205,7 +205,16 @@ if ( $location ) { if ( ! empty( $_REQUEST['paged'] ) ) { $location = add_query_arg( 'paged', (int) $_REQUEST['paged'], $location ); } - wp_redirect( $location ); + + /** + * Filters the taxonomy redirect destination URL. + * + * @since 4.6.0 + * + * @param string $location The destination URL. + * @param object $tax The taxonomy object. + */ + wp_redirect( apply_filters( 'redirect_term_location', $location, $tax ) ); exit; } @@ -288,7 +297,7 @@ require_once( ABSPATH . 'wp-admin/admin-header.php' ); if ( ! current_user_can( $tax->cap->edit_terms ) ) { wp_die( '' . __( 'You are not allowed to edit this item.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit this item.' ) . '
', 403 ); } @@ -321,87 +330,21 @@ if ( isset( $_REQUEST['s'] ) && strlen( $_REQUEST['s'] ) ) { endif; ?> - -
- ' . __( 'Note:' ) . '
';
- printf(
- /* translators: %s: default category */
- __( 'Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the category %s.' ),
- /** This filter is documented in wp-includes/category-template.php */
- '' . apply_filters( 'the_category', get_cat_name( get_option( 'default_category') ) ) . ''
- );
- ?>
-
category to tag converter.' ), esc_url( $import_link ) ) ?>
- -tag to category converter.' ), esc_url( $import_link ) ) ;?>
-
+ ' . __( 'Note:' ) . '
';
+ printf(
+ /* translators: %s: default category */
+ __( 'Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the category %s.' ),
+ /** This filter is documented in wp-includes/category-template.php */
+ '' . apply_filters( 'the_category', get_cat_name( get_option( 'default_category') ) ) . ''
+ );
+ ?>
+
category to tag converter.' ), esc_url( $import_link ) ) ?>
+ +tag to category converter.' ), esc_url( $import_link ) ) ;?>
+' . __( 'You are not allowed to edit posts in this post type.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit posts in this post type.' ) . '
', 403 ); } @@ -103,7 +103,7 @@ if ( $doaction ) { foreach ( (array) $post_ids as $post_id ) { if ( !current_user_can( 'delete_post', $post_id) ) - wp_die( __('You are not allowed to move this item to the Trash.') ); + wp_die( __('Sorry, you are not allowed to move this item to the Trash.') ); if ( wp_check_post_lock( $post_id ) ) { $locked++; @@ -122,7 +122,7 @@ if ( $doaction ) { $untrashed = 0; foreach ( (array) $post_ids as $post_id ) { if ( !current_user_can( 'delete_post', $post_id) ) - wp_die( __('You are not allowed to restore this item from the Trash.') ); + wp_die( __('Sorry, you are not allowed to restore this item from the Trash.') ); if ( !wp_untrash_post($post_id) ) wp_die( __('Error in restoring from Trash.') ); @@ -137,7 +137,7 @@ if ( $doaction ) { $post_del = get_post($post_id); if ( !current_user_can( 'delete_post', $post_id ) ) - wp_die( __('You are not allowed to delete this item.') ); + wp_die( __('Sorry, you are not allowed to delete this item.') ); if ( $post_del->post_type == 'attachment' ) { if ( ! wp_delete_attachment($post_id) ) @@ -194,7 +194,7 @@ if ( 'post' == $post_type ) { '' . __('You can customize the display of this screen’s contents in a number of ways:') . '
' . 'Free Software Foundation.' ); ?>
+Free Software Foundation.' ); ?>
' . __('Support Forums') . '
' ); -if ( current_user_can( 'install_plugins' ) ) +if ( current_user_can( 'install_plugins' ) ) { + // List of popular importer plugins from the WordPress.org API. $popular_importers = wp_get_popular_importers(); -else - $popular_importers = array(); +} else { + $popular_importers = array(); +} // Detect and redirect invalid importers like 'movabletype', which is registered as 'mt' if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid'] ] ) ) { @@ -46,6 +49,7 @@ if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid'] add_thickbox(); wp_enqueue_script( 'plugin-install' ); +wp_enqueue_script( 'updates' ); require_once( ABSPATH . 'wp-admin/admin-header.php' ); $parent_file = 'tools.php'; @@ -64,7 +68,7 @@ $parent_file = 'tools.php'; $pop_data ) { continue; if ( isset( $importers[ $pop_data['importer-id'] ] ) ) continue; + + // Fill the array of registered (already installed) importers with data of the popular importers from the WordPress.org API. $importers[ $pop_data['importer-id'] ] = array( $pop_data['name'], $pop_data['description'], 'install' => $pop_data['plugin-slug'] ); } @@ -83,43 +89,106 @@ if ( empty( $importers ) ) { ?>$action | -{$data[1]} | +
+ {$data[0]} + {$action} + | ++ {$data[1]} + |
' . __( 'You do not have sufficient permissions to edit the links for this site.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit the links for this site.' ) . '
', 403 ); } @@ -131,11 +131,11 @@ function wp_get_link_cats( $link_id = 0 ) { * * @since 2.0.0 * - * @param int $link_id ID of link to retrieve. + * @param int|stdClass $link Link ID or object to retrieve. * @return object Link object for editing. */ -function get_link_to_edit( $link_id ) { - return get_bookmark( $link_id, OBJECT, 'edit' ); +function get_link_to_edit( $link ) { + return get_bookmark( $link, OBJECT, 'edit' ); } /** @@ -312,5 +312,5 @@ function wp_link_manager_disabled_message() { wp_die( sprintf( __( 'If you are looking to use the link manager, please install the Link Manager plugin.' ), $link ) ); } - wp_die( __( 'You do not have sufficient permissions to edit the links for this site.' ) ); + wp_die( __( 'Sorry, you are not allowed to edit the links for this site.' ) ); } diff --git a/wp-admin/includes/class-automatic-upgrader-skin.php b/wp-admin/includes/class-automatic-upgrader-skin.php new file mode 100644 index 00000000..23fab8b4 --- /dev/null +++ b/wp-admin/includes/class-automatic-upgrader-skin.php @@ -0,0 +1,115 @@ +options['context'] = $context; + } + // TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version + // This will output a credentials form in event of failure, We don't want that, so just hide with a buffer + ob_start(); + $result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership ); + ob_end_clean(); + return $result; + } + + /** + * @access public + * + * @return array + */ + public function get_upgrade_messages() { + return $this->messages; + } + + /** + * @param string|array|WP_Error $data + */ + public function feedback( $data ) { + if ( is_wp_error( $data ) ) { + $string = $data->get_error_message(); + } elseif ( is_array( $data ) ) { + return; + } else { + $string = $data; + } + if ( ! empty( $this->upgrader->strings[ $string ] ) ) + $string = $this->upgrader->strings[ $string ]; + + if ( strpos( $string, '%' ) !== false ) { + $args = func_get_args(); + $args = array_splice( $args, 1 ); + if ( ! empty( $args ) ) + $string = vsprintf( $string, $args ); + } + + $string = trim( $string ); + + // Only allow basic HTML in the messages, as it'll be used in emails/logs rather than direct browser output. + $string = wp_kses( $string, array( + 'a' => array( + 'href' => true + ), + 'br' => true, + 'em' => true, + 'strong' => true, + ) ); + + if ( empty( $string ) ) + return; + + $this->messages[] = $string; + } + + /** + * @access public + */ + public function header() { + ob_start(); + } + + /** + * @access public + */ + public function footer() { + $output = ob_get_clean(); + if ( ! empty( $output ) ) + $this->feedback( $output ); + } +} diff --git a/wp-admin/includes/class-bulk-plugin-upgrader-skin.php b/wp-admin/includes/class-bulk-plugin-upgrader-skin.php new file mode 100644 index 00000000..1441c90b --- /dev/null +++ b/wp-admin/includes/class-bulk-plugin-upgrader-skin.php @@ -0,0 +1,68 @@ +upgrader->strings['skin_before_update_header'] = __('Updating Plugin %1$s (%2$d/%3$d)'); + } + + /** + * + * @param string $title + */ + public function before($title = '') { + parent::before($this->plugin_info['Title']); + } + + /** + * + * @param string $title + */ + public function after($title = '') { + parent::after($this->plugin_info['Title']); + $this->decrement_update_count( 'plugin' ); + } + + /** + * @access public + */ + public function bulk_footer() { + parent::bulk_footer(); + $update_actions = array( + 'plugins_page' => '' . __( 'Return to Plugins page' ) . '', + 'updates_page' => '' . __( 'Return to WordPress Updates page' ) . '' + ); + if ( ! current_user_can( 'activate_plugins' ) ) + unset( $update_actions['plugins_page'] ); + + /** + * Filters the list of action links available following bulk plugin updates. + * + * @since 3.0.0 + * + * @param array $update_actions Array of plugin action links. + * @param array $plugin_info Array of information for the last-updated plugin. + */ + $update_actions = apply_filters( 'update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info ); + + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } +} diff --git a/wp-admin/includes/class-bulk-theme-upgrader-skin.php b/wp-admin/includes/class-bulk-theme-upgrader-skin.php new file mode 100644 index 00000000..dba4c0bf --- /dev/null +++ b/wp-admin/includes/class-bulk-theme-upgrader-skin.php @@ -0,0 +1,68 @@ +upgrader->strings['skin_before_update_header'] = __('Updating Theme %1$s (%2$d/%3$d)'); + } + + /** + * + * @param string $title + */ + public function before($title = '') { + parent::before( $this->theme_info->display('Name') ); + } + + /** + * + * @param string $title + */ + public function after($title = '') { + parent::after( $this->theme_info->display('Name') ); + $this->decrement_update_count( 'theme' ); + } + + /** + * @access public + */ + public function bulk_footer() { + parent::bulk_footer(); + $update_actions = array( + 'themes_page' => '' . __( 'Return to Themes page' ) . '', + 'updates_page' => '' . __( 'Return to WordPress Updates page' ) . '' + ); + if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) + unset( $update_actions['themes_page'] ); + + /** + * Filters the list of action links available following bulk theme updates. + * + * @since 3.0.0 + * + * @param array $update_actions Array of theme action links. + * @param array $theme_info Array of information for the last-updated theme. + */ + $update_actions = apply_filters( 'update_bulk_theme_complete_actions', $update_actions, $this->theme_info ); + + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } +} diff --git a/wp-admin/includes/class-bulk-upgrader-skin.php b/wp-admin/includes/class-bulk-upgrader-skin.php new file mode 100644 index 00000000..16f410fd --- /dev/null +++ b/wp-admin/includes/class-bulk-upgrader-skin.php @@ -0,0 +1,175 @@ + '', 'nonce' => '' ); + $args = wp_parse_args($args, $defaults); + + parent::__construct($args); + } + + /** + * @access public + */ + public function add_strings() { + $this->upgrader->strings['skin_upgrade_start'] = __('The update process is starting. This process may take a while on some hosts, so please be patient.'); + /* translators: 1: Title of an update, 2: Error message */ + $this->upgrader->strings['skin_update_failed_error'] = __('An error occurred while updating %1$s: %2$s'); + /* translators: 1: Title of an update */ + $this->upgrader->strings['skin_update_failed'] = __('The update of %1$s failed.'); + /* translators: 1: Title of an update */ + $this->upgrader->strings['skin_update_successful'] = __( '%1$s updated successfully.' ) . ' '; + $this->upgrader->strings['skin_upgrade_end'] = __('All updates have been completed.'); + } + + /** + * @param string $string + */ + public function feedback($string) { + if ( isset( $this->upgrader->strings[$string] ) ) + $string = $this->upgrader->strings[$string]; + + if ( strpos($string, '%') !== false ) { + $args = func_get_args(); + $args = array_splice($args, 1); + if ( $args ) { + $args = array_map( 'strip_tags', $args ); + $args = array_map( 'esc_html', $args ); + $string = vsprintf($string, $args); + } + } + if ( empty($string) ) + return; + if ( $this->in_loop ) + echo "$string$string
\n"; + } + + /** + * @access public + */ + public function header() { + // Nothing, This will be displayed within a iframe. + } + + /** + * @access public + */ + public function footer() { + // Nothing, This will be displayed within a iframe. + } + + /** + * + * @param string|WP_Error $error + */ + public function error($error) { + if ( is_string($error) && isset( $this->upgrader->strings[$error] ) ) + $this->error = $this->upgrader->strings[$error]; + + if ( is_wp_error($error) ) { + $messages = array(); + foreach ( $error->get_error_messages() as $emessage ) { + if ( $error->get_error_data() && is_string( $error->get_error_data() ) ) + $messages[] = $emessage . ' ' . esc_html( strip_tags( $error->get_error_data() ) ); + else + $messages[] = $emessage; + } + $this->error = implode(', ', $messages); + } + echo ''; + } + + /** + * @access public + */ + public function bulk_header() { + $this->feedback('skin_upgrade_start'); + } + + /** + * @access public + */ + public function bulk_footer() { + $this->feedback('skin_upgrade_end'); + } + + /** + * + * @param string $title + */ + public function before($title = '') { + $this->in_loop = true; + printf( '' . sprintf($this->upgrader->strings['skin_update_failed_error'], $title, '' . $this->error . '' ) . '
' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '
' . sprintf($this->upgrader->strings['skin_update_successful'], $title, 'jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').toggle();jQuery(\'span\', this).toggle(); return false;') . '
.po
',
+ '.mo
'
+ )
+ );
+ }
+
+ return $source;
+ }
+
+ /**
+ * Get the name of an item being updated.
+ *
+ * @since 3.7.0
+ * @access public
+ *
+ * @param object $update The data for an update.
+ * @return string The name of the item being updated.
+ */
+ public function get_name_for_update( $update ) {
+ switch ( $update->type ) {
+ case 'core':
+ return 'WordPress'; // Not translated
+
+ case 'theme':
+ $theme = wp_get_theme( $update->slug );
+ if ( $theme->exists() )
+ return $theme->Get( 'Name' );
+ break;
+ case 'plugin':
+ $plugin_data = get_plugins( '/' . $update->slug );
+ $plugin_data = reset( $plugin_data );
+ if ( $plugin_data )
+ return $plugin_data['Name'];
+ break;
+ }
+ return '';
+ }
+
+}
diff --git a/wp-admin/includes/class-pclzip.php b/wp-admin/includes/class-pclzip.php
index f36a4a3e..ae0af7a8 100644
--- a/wp-admin/includes/class-pclzip.php
+++ b/wp-admin/includes/class-pclzip.php
@@ -1839,18 +1839,19 @@
// ----- Get 'memory_limit' configuration value
$v_memory_limit = ini_get('memory_limit');
$v_memory_limit = trim($v_memory_limit);
+ $v_memory_limit_int = (int) $v_memory_limit;
$last = strtolower(substr($v_memory_limit, -1));
if($last == 'g')
- //$v_memory_limit = $v_memory_limit*1024*1024*1024;
- $v_memory_limit = $v_memory_limit*1073741824;
+ //$v_memory_limit_int = $v_memory_limit_int*1024*1024*1024;
+ $v_memory_limit_int = $v_memory_limit_int*1073741824;
if($last == 'm')
- //$v_memory_limit = $v_memory_limit*1024*1024;
- $v_memory_limit = $v_memory_limit*1048576;
+ //$v_memory_limit_int = $v_memory_limit_int*1024*1024;
+ $v_memory_limit_int = $v_memory_limit_int*1048576;
if($last == 'k')
- $v_memory_limit = $v_memory_limit*1024;
+ $v_memory_limit_int = $v_memory_limit_int*1024;
- $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
+ $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit_int*PCLZIP_TEMPORARY_FILE_RATIO);
// ----- Sanity check : No threshold if value lower than 1M
diff --git a/wp-admin/includes/class-plugin-installer-skin.php b/wp-admin/includes/class-plugin-installer-skin.php
new file mode 100644
index 00000000..34b20203
--- /dev/null
+++ b/wp-admin/includes/class-plugin-installer-skin.php
@@ -0,0 +1,96 @@
+ 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' );
+ $args = wp_parse_args($args, $defaults);
+
+ $this->type = $args['type'];
+ $this->api = isset($args['api']) ? $args['api'] : array();
+
+ parent::__construct($args);
+ }
+
+ /**
+ * @access public
+ */
+ public function before() {
+ if ( !empty($this->api) )
+ $this->upgrader->strings['process_success'] = sprintf( __('Successfully installed the plugin %s %s.'), $this->api->name, $this->api->version);
+ }
+
+ /**
+ * @access public
+ */
+ public function after() {
+ $plugin_file = $this->upgrader->plugin_info();
+
+ $install_actions = array();
+
+ $from = isset($_GET['from']) ? wp_unslash( $_GET['from'] ) : 'plugins';
+
+ if ( 'import' == $from )
+ $install_actions['activate_plugin'] = '' . __( 'Activate Plugin & Run Importer' ) . '';
+ else
+ $install_actions['activate_plugin'] = '' . __( 'Activate Plugin' ) . '';
+
+ if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
+ $install_actions['network_activate'] = '' . __( 'Network Activate' ) . '';
+ unset( $install_actions['activate_plugin'] );
+ }
+
+ if ( 'import' == $from ) {
+ $install_actions['importers_page'] = '' . __( 'Return to Importers' ) . '';
+ } elseif ( $this->type == 'web' ) {
+ $install_actions['plugins_page'] = '' . __( 'Return to Plugin Installer' ) . '';
+ } elseif ( 'upload' == $this->type && 'plugins' == $from ) {
+ $install_actions['plugins_page'] = '' . __( 'Return to Plugin Installer' ) . '';
+ } else {
+ $install_actions['plugins_page'] = '' . __( 'Return to Plugins page' ) . '';
+ }
+
+ if ( ! $this->result || is_wp_error($this->result) ) {
+ unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
+ } elseif ( ! current_user_can( 'activate_plugins' ) ) {
+ unset( $install_actions['activate_plugin'] );
+ }
+
+ /**
+ * Filters the list of action links available following a single plugin installation.
+ *
+ * @since 2.7.0
+ *
+ * @param array $install_actions Array of plugin action links.
+ * @param object $api Object containing WordPress.org API plugin data. Empty
+ * for non-API installs, such as when a plugin is installed
+ * via upload.
+ * @param string $plugin_file Path to the plugin file.
+ */
+ $install_actions = apply_filters( 'install_plugin_complete_actions', $install_actions, $this->api, $plugin_file );
+
+ if ( ! empty($install_actions) )
+ $this->feedback(implode(' | ', (array)$install_actions));
+ }
+}
diff --git a/wp-admin/includes/class-plugin-upgrader-skin.php b/wp-admin/includes/class-plugin-upgrader-skin.php
new file mode 100644
index 00000000..1c4da874
--- /dev/null
+++ b/wp-admin/includes/class-plugin-upgrader-skin.php
@@ -0,0 +1,71 @@
+ '', 'plugin' => '', 'nonce' => '', 'title' => __('Update Plugin') );
+ $args = wp_parse_args($args, $defaults);
+
+ $this->plugin = $args['plugin'];
+
+ $this->plugin_active = is_plugin_active( $this->plugin );
+ $this->plugin_network_active = is_plugin_active_for_network( $this->plugin );
+
+ parent::__construct($args);
+ }
+
+ /**
+ * @access public
+ */
+ public function after() {
+ $this->plugin = $this->upgrader->plugin_info();
+ if ( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){
+ // Currently used only when JS is off for a single plugin update?
+ echo '';
+ }
+
+ $this->decrement_update_count( 'plugin' );
+
+ $update_actions = array(
+ 'activate_plugin' => '' . __( 'Activate Plugin' ) . '',
+ 'plugins_page' => '' . __( 'Return to Plugins page' ) . ''
+ );
+ if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugins' ) )
+ unset( $update_actions['activate_plugin'] );
+
+ /**
+ * Filters the list of action links available following a single plugin update.
+ *
+ * @since 2.7.0
+ *
+ * @param array $update_actions Array of plugin action links.
+ * @param string $plugin Path to the plugin file.
+ */
+ $update_actions = apply_filters( 'update_plugin_complete_actions', $update_actions, $this->plugin );
+
+ if ( ! empty($update_actions) )
+ $this->feedback(implode(' | ', (array)$update_actions));
+ }
+}
diff --git a/wp-admin/includes/class-plugin-upgrader.php b/wp-admin/includes/class-plugin-upgrader.php
new file mode 100644
index 00000000..ffb46204
--- /dev/null
+++ b/wp-admin/includes/class-plugin-upgrader.php
@@ -0,0 +1,466 @@
+strings['up_to_date'] = __('The plugin is at the latest version.');
+ $this->strings['no_package'] = __('Update package not available.');
+ $this->strings['downloading_package'] = __('Downloading update from %s…');
+ $this->strings['unpack_package'] = __('Unpacking the update…');
+ $this->strings['remove_old'] = __('Removing the old version of the plugin…');
+ $this->strings['remove_old_failed'] = __('Could not remove the old plugin.');
+ $this->strings['process_failed'] = __('Plugin update failed.');
+ $this->strings['process_success'] = __('Plugin updated successfully.');
+ $this->strings['process_bulk_success'] = __('Plugins updated successfully.');
+ }
+
+ /**
+ * Initialize the install strings.
+ *
+ * @since 2.8.0
+ * @access public
+ */
+ public function install_strings() {
+ $this->strings['no_package'] = __('Install package not available.');
+ $this->strings['downloading_package'] = __('Downloading install package from %s…');
+ $this->strings['unpack_package'] = __('Unpacking the package…');
+ $this->strings['installing_package'] = __('Installing the plugin…');
+ $this->strings['no_files'] = __('The plugin contains no files.');
+ $this->strings['process_failed'] = __('Plugin install failed.');
+ $this->strings['process_success'] = __('Plugin installed successfully.');
+ }
+
+ /**
+ * Install a plugin package.
+ *
+ * @since 2.8.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
+ *
+ * @param string $package The full local path or URI of the package.
+ * @param array $args {
+ * Optional. Other arguments for installing a plugin package. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
+ * Default true.
+ * }
+ * @return bool|WP_Error True if the install was successful, false or a WP_Error otherwise.
+ */
+ public function install( $package, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->install_strings();
+
+ add_filter('upgrader_source_selection', array($this, 'check_package') );
+ // Clear cache so wp_update_plugins() knows about the new plugin.
+ add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
+
+ $this->run( array(
+ 'package' => $package,
+ 'destination' => WP_PLUGIN_DIR,
+ 'clear_destination' => false, // Do not overwrite files.
+ 'clear_working' => true,
+ 'hook_extra' => array(
+ 'type' => 'plugin',
+ 'action' => 'install',
+ )
+ ) );
+
+ remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
+ remove_filter('upgrader_source_selection', array($this, 'check_package') );
+
+ if ( ! $this->result || is_wp_error($this->result) )
+ return $this->result;
+
+ // Force refresh of plugin update information
+ wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
+
+ return true;
+ }
+
+ /**
+ * Upgrade a plugin.
+ *
+ * @since 2.8.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
+ *
+ * @param string $plugin The basename path to the main plugin file.
+ * @param array $args {
+ * Optional. Other arguments for upgrading a plugin package. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
+ * Default true.
+ * }
+ * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise.
+ */
+ public function upgrade( $plugin, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->upgrade_strings();
+
+ $current = get_site_transient( 'update_plugins' );
+ if ( !isset( $current->response[ $plugin ] ) ) {
+ $this->skin->before();
+ $this->skin->set_result(false);
+ $this->skin->error('up_to_date');
+ $this->skin->after();
+ return false;
+ }
+
+ // Get the URL to the zip file
+ $r = $current->response[ $plugin ];
+
+ add_filter('upgrader_pre_install', array($this, 'deactivate_plugin_before_upgrade'), 10, 2);
+ add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4);
+ //'source_selection' => array($this, 'source_selection'), //there's a trac ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins.
+ // Clear cache so wp_update_plugins() knows about the new plugin.
+ add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
+
+ $this->run( array(
+ 'package' => $r->package,
+ 'destination' => WP_PLUGIN_DIR,
+ 'clear_destination' => true,
+ 'clear_working' => true,
+ 'hook_extra' => array(
+ 'plugin' => $plugin,
+ 'type' => 'plugin',
+ 'action' => 'update',
+ ),
+ ) );
+
+ // Cleanup our hooks, in case something else does a upgrade on this connection.
+ remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
+ remove_filter('upgrader_pre_install', array($this, 'deactivate_plugin_before_upgrade'));
+ remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'));
+
+ if ( ! $this->result || is_wp_error($this->result) )
+ return $this->result;
+
+ // Force refresh of plugin update information
+ wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
+
+ return true;
+ }
+
+ /**
+ * Bulk upgrade several plugins at once.
+ *
+ * @since 2.8.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
+ *
+ * @param array $plugins Array of the basename paths of the plugins' main files.
+ * @param array $args {
+ * Optional. Other arguments for upgrading several plugins at once. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
+ * Default true.
+ * }
+ * @return array|false An array of results indexed by plugin file, or false if unable to connect to the filesystem.
+ */
+ public function bulk_upgrade( $plugins, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->bulk = true;
+ $this->upgrade_strings();
+
+ $current = get_site_transient( 'update_plugins' );
+
+ add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4);
+ add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
+
+ $this->skin->header();
+
+ // Connect to the Filesystem first.
+ $res = $this->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) );
+ if ( ! $res ) {
+ $this->skin->footer();
+ return false;
+ }
+
+ $this->skin->bulk_header();
+
+ /*
+ * Only start maintenance mode if:
+ * - running Multisite and there are one or more plugins specified, OR
+ * - a plugin with an update available is currently active.
+ * @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
+ */
+ $maintenance = ( is_multisite() && ! empty( $plugins ) );
+ foreach ( $plugins as $plugin )
+ $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
+ if ( $maintenance )
+ $this->maintenance_mode(true);
+
+ $results = array();
+
+ $this->update_count = count($plugins);
+ $this->update_current = 0;
+ foreach ( $plugins as $plugin ) {
+ $this->update_current++;
+ $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
+
+ if ( !isset( $current->response[ $plugin ] ) ) {
+ $this->skin->set_result('up_to_date');
+ $this->skin->before();
+ $this->skin->feedback('up_to_date');
+ $this->skin->after();
+ $results[$plugin] = true;
+ continue;
+ }
+
+ // Get the URL to the zip file.
+ $r = $current->response[ $plugin ];
+
+ $this->skin->plugin_active = is_plugin_active($plugin);
+
+ $result = $this->run( array(
+ 'package' => $r->package,
+ 'destination' => WP_PLUGIN_DIR,
+ 'clear_destination' => true,
+ 'clear_working' => true,
+ 'is_multi' => true,
+ 'hook_extra' => array(
+ 'plugin' => $plugin
+ )
+ ) );
+
+ $results[$plugin] = $this->result;
+
+ // Prevent credentials auth screen from displaying multiple times
+ if ( false === $result )
+ break;
+ } //end foreach $plugins
+
+ $this->maintenance_mode(false);
+
+ /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
+ do_action( 'upgrader_process_complete', $this, array(
+ 'action' => 'update',
+ 'type' => 'plugin',
+ 'bulk' => true,
+ 'plugins' => $plugins,
+ ) );
+
+ $this->skin->bulk_footer();
+
+ $this->skin->footer();
+
+ // Cleanup our hooks, in case something else does a upgrade on this connection.
+ remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
+ remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'));
+
+ // Force refresh of plugin update information.
+ wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
+
+ return $results;
+ }
+
+ /**
+ * Check a source package to be sure it contains a plugin.
+ *
+ * This function is added to the {@see 'upgrader_source_selection'} filter by
+ * Plugin_Upgrader::install().
+ *
+ * @since 3.3.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param string $source The path to the downloaded package source.
+ * @return string|WP_Error The source as passed, or a WP_Error object
+ * if no plugins were found.
+ */
+ public function check_package($source) {
+ global $wp_filesystem;
+
+ if ( is_wp_error($source) )
+ return $source;
+
+ $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source);
+ if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, let's not prevent installation.
+ return $source;
+
+ // Check the folder contains at least 1 valid plugin.
+ $plugins_found = false;
+ $files = glob( $working_directory . '*.php' );
+ if ( $files ) {
+ foreach ( $files as $file ) {
+ $info = get_plugin_data( $file, false, false );
+ if ( ! empty( $info['Name'] ) ) {
+ $plugins_found = true;
+ break;
+ }
+ }
+ }
+
+ if ( ! $plugins_found )
+ return new WP_Error( 'incompatible_archive_no_plugins', $this->strings['incompatible_archive'], __( 'No valid plugins were found.' ) );
+
+ return $source;
+ }
+
+ /**
+ * Retrieve the path to the file that contains the plugin info.
+ *
+ * This isn't used internally in the class, but is called by the skins.
+ *
+ * @since 2.8.0
+ * @access public
+ *
+ * @return string|false The full path to the main plugin file, or false.
+ */
+ public function plugin_info() {
+ if ( ! is_array($this->result) )
+ return false;
+ if ( empty($this->result['destination_name']) )
+ return false;
+
+ $plugin = get_plugins('/' . $this->result['destination_name']); //Ensure to pass with leading slash
+ if ( empty($plugin) )
+ return false;
+
+ $pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list
+
+ return $this->result['destination_name'] . '/' . $pluginfiles[0];
+ }
+
+ /**
+ * Deactivates a plugin before it is upgraded.
+ *
+ * Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade().
+ *
+ * @since 2.8.0
+ * @since 4.1.0 Added a return value.
+ * @access public
+ *
+ * @param bool|WP_Error $return Upgrade offer return.
+ * @param array $plugin Plugin package arguments.
+ * @return bool|WP_Error The passed in $return param or WP_Error.
+ */
+ public function deactivate_plugin_before_upgrade($return, $plugin) {
+
+ if ( is_wp_error($return) ) //Bypass.
+ return $return;
+
+ // When in cron (background updates) don't deactivate the plugin, as we require a browser to reactivate it
+ if ( defined( 'DOING_CRON' ) && DOING_CRON )
+ return $return;
+
+ $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
+ if ( empty($plugin) )
+ return new WP_Error('bad_request', $this->strings['bad_request']);
+
+ if ( is_plugin_active($plugin) ) {
+ //Deactivate the plugin silently, Prevent deactivation hooks from running.
+ deactivate_plugins($plugin, true);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Delete the old plugin during an upgrade.
+ *
+ * Hooked to the {@see 'upgrader_clear_destination'} filter by
+ * Plugin_Upgrader::upgrade() and Plugin_Upgrader::bulk_upgrade().
+ *
+ * @since 2.8.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param bool|WP_Error $removed
+ * @param string $local_destination
+ * @param string $remote_destination
+ * @param array $plugin
+ * @return WP_Error|bool
+ */
+ public function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) {
+ global $wp_filesystem;
+
+ if ( is_wp_error($removed) )
+ return $removed; //Pass errors through.
+
+ $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
+ if ( empty($plugin) )
+ return new WP_Error('bad_request', $this->strings['bad_request']);
+
+ $plugins_dir = $wp_filesystem->wp_plugins_dir();
+ $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin) );
+
+ if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If it's already vanished.
+ return $removed;
+
+ // If plugin is in its own directory, recursively delete the directory.
+ if ( strpos($plugin, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory separator AND that it's not the root plugin folder
+ $deleted = $wp_filesystem->delete($this_plugin_dir, true);
+ else
+ $deleted = $wp_filesystem->delete($plugins_dir . $plugin);
+
+ if ( ! $deleted )
+ return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
+
+ return true;
+ }
+}
diff --git a/wp-admin/includes/class-theme-installer-skin.php b/wp-admin/includes/class-theme-installer-skin.php
new file mode 100644
index 00000000..57c78108
--- /dev/null
+++ b/wp-admin/includes/class-theme-installer-skin.php
@@ -0,0 +1,98 @@
+ 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' );
+ $args = wp_parse_args($args, $defaults);
+
+ $this->type = $args['type'];
+ $this->api = isset($args['api']) ? $args['api'] : array();
+
+ parent::__construct($args);
+ }
+
+ /**
+ * @access public
+ */
+ public function before() {
+ if ( !empty($this->api) )
+ $this->upgrader->strings['process_success'] = sprintf( $this->upgrader->strings['process_success_specific'], $this->api->name, $this->api->version);
+ }
+
+ /**
+ * @access public
+ */
+ public function after() {
+ if ( empty($this->upgrader->result['destination_name']) )
+ return;
+
+ $theme_info = $this->upgrader->theme_info();
+ if ( empty( $theme_info ) )
+ return;
+
+ $name = $theme_info->display('Name');
+ $stylesheet = $this->upgrader->result['destination_name'];
+ $template = $theme_info->get_template();
+
+ $activate_link = add_query_arg( array(
+ 'action' => 'activate',
+ 'template' => urlencode( $template ),
+ 'stylesheet' => urlencode( $stylesheet ),
+ ), admin_url('themes.php') );
+ $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
+
+ $install_actions = array();
+
+ if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
+ $install_actions['preview'] = ' ';
+ }
+ $install_actions['activate'] = '' . sprintf( __( 'Activate “%s”' ), $name ) . '';
+
+ if ( is_network_admin() && current_user_can( 'manage_network_themes' ) )
+ $install_actions['network_enable'] = '' . __( 'Network Enable' ) . '';
+
+ if ( $this->type == 'web' )
+ $install_actions['themes_page'] = '' . __( 'Return to Theme Installer' ) . '';
+ elseif ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) )
+ $install_actions['themes_page'] = '' . __( 'Return to Themes page' ) . '';
+
+ if ( ! $this->result || is_wp_error($this->result) || is_network_admin() || ! current_user_can( 'switch_themes' ) )
+ unset( $install_actions['activate'], $install_actions['preview'] );
+
+ /**
+ * Filters the list of action links available following a single theme installation.
+ *
+ * @since 2.8.0
+ *
+ * @param array $install_actions Array of theme action links.
+ * @param object $api Object containing WordPress.org API theme data.
+ * @param string $stylesheet Theme directory name.
+ * @param WP_Theme $theme_info Theme object.
+ */
+ $install_actions = apply_filters( 'install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info );
+ if ( ! empty($install_actions) )
+ $this->feedback(implode(' | ', (array)$install_actions));
+ }
+}
diff --git a/wp-admin/includes/class-theme-upgrader-skin.php b/wp-admin/includes/class-theme-upgrader-skin.php
new file mode 100644
index 00000000..329582ee
--- /dev/null
+++ b/wp-admin/includes/class-theme-upgrader-skin.php
@@ -0,0 +1,83 @@
+ '', 'theme' => '', 'nonce' => '', 'title' => __('Update Theme') );
+ $args = wp_parse_args($args, $defaults);
+
+ $this->theme = $args['theme'];
+
+ parent::__construct($args);
+ }
+
+ /**
+ * @access public
+ */
+ public function after() {
+ $this->decrement_update_count( 'theme' );
+
+ $update_actions = array();
+ if ( ! empty( $this->upgrader->result['destination_name'] ) && $theme_info = $this->upgrader->theme_info() ) {
+ $name = $theme_info->display('Name');
+ $stylesheet = $this->upgrader->result['destination_name'];
+ $template = $theme_info->get_template();
+
+ $activate_link = add_query_arg( array(
+ 'action' => 'activate',
+ 'template' => urlencode( $template ),
+ 'stylesheet' => urlencode( $stylesheet ),
+ ), admin_url('themes.php') );
+ $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
+
+ if ( get_stylesheet() == $stylesheet ) {
+ if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
+ $update_actions['preview'] = ' ';
+ }
+ } elseif ( current_user_can( 'switch_themes' ) ) {
+ if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
+ $update_actions['preview'] = ' ';
+ }
+ $update_actions['activate'] = '' . sprintf( __( 'Activate “%s”' ), $name ) . '';
+ }
+
+ if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() )
+ unset( $update_actions['preview'], $update_actions['activate'] );
+ }
+
+ $update_actions['themes_page'] = '' . __( 'Return to Themes page' ) . '';
+
+ /**
+ * Filters the list of action links available following a single theme update.
+ *
+ * @since 2.8.0
+ *
+ * @param array $update_actions Array of theme action links.
+ * @param string $theme Theme directory name.
+ */
+ $update_actions = apply_filters( 'update_theme_complete_actions', $update_actions, $this->theme );
+
+ if ( ! empty($update_actions) )
+ $this->feedback(implode(' | ', (array)$update_actions));
+ }
+}
diff --git a/wp-admin/includes/class-theme-upgrader.php b/wp-admin/includes/class-theme-upgrader.php
new file mode 100644
index 00000000..76129e34
--- /dev/null
+++ b/wp-admin/includes/class-theme-upgrader.php
@@ -0,0 +1,603 @@
+strings['up_to_date'] = __('The theme is at the latest version.');
+ $this->strings['no_package'] = __('Update package not available.');
+ $this->strings['downloading_package'] = __('Downloading update from %s…');
+ $this->strings['unpack_package'] = __('Unpacking the update…');
+ $this->strings['remove_old'] = __('Removing the old version of the theme…');
+ $this->strings['remove_old_failed'] = __('Could not remove the old theme.');
+ $this->strings['process_failed'] = __('Theme update failed.');
+ $this->strings['process_success'] = __('Theme updated successfully.');
+ }
+
+ /**
+ * Initialize the install strings.
+ *
+ * @since 2.8.0
+ * @access public
+ */
+ public function install_strings() {
+ $this->strings['no_package'] = __('Install package not available.');
+ $this->strings['downloading_package'] = __('Downloading install package from %s…');
+ $this->strings['unpack_package'] = __('Unpacking the package…');
+ $this->strings['installing_package'] = __('Installing the theme…');
+ $this->strings['no_files'] = __('The theme contains no files.');
+ $this->strings['process_failed'] = __('Theme install failed.');
+ $this->strings['process_success'] = __('Theme installed successfully.');
+ /* translators: 1: theme name, 2: version */
+ $this->strings['process_success_specific'] = __('Successfully installed the theme %1$s %2$s.');
+ $this->strings['parent_theme_search'] = __('This theme requires a parent theme. Checking if it is installed…');
+ /* translators: 1: theme name, 2: version */
+ $this->strings['parent_theme_prepare_install'] = __('Preparing to install %1$s %2$s…');
+ /* translators: 1: theme name, 2: version */
+ $this->strings['parent_theme_currently_installed'] = __('The parent theme, %1$s %2$s, is currently installed.');
+ /* translators: 1: theme name, 2: version */
+ $this->strings['parent_theme_install_success'] = __('Successfully installed the parent theme, %1$s %2$s.');
+ $this->strings['parent_theme_not_found'] = __('The parent theme could not be found. You will need to install the parent theme, %s, before you can use this child theme.');
+ }
+
+ /**
+ * Check if a child theme is being installed and we need to install its parent.
+ *
+ * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::install().
+ *
+ * @since 3.4.0
+ * @access public
+ *
+ * @param bool $install_result
+ * @param array $hook_extra
+ * @param array $child_result
+ * @return type
+ */
+ public function check_parent_theme_filter( $install_result, $hook_extra, $child_result ) {
+ // Check to see if we need to install a parent theme
+ $theme_info = $this->theme_info();
+
+ if ( ! $theme_info->parent() )
+ return $install_result;
+
+ $this->skin->feedback( 'parent_theme_search' );
+
+ if ( ! $theme_info->parent()->errors() ) {
+ $this->skin->feedback( 'parent_theme_currently_installed', $theme_info->parent()->display('Name'), $theme_info->parent()->display('Version') );
+ // We already have the theme, fall through.
+ return $install_result;
+ }
+
+ // We don't have the parent theme, let's install it.
+ $api = themes_api('theme_information', array('slug' => $theme_info->get('Template'), 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth.
+
+ if ( ! $api || is_wp_error($api) ) {
+ $this->skin->feedback( 'parent_theme_not_found', $theme_info->get('Template') );
+ // Don't show activate or preview actions after install
+ add_filter('install_theme_complete_actions', array($this, 'hide_activate_preview_actions') );
+ return $install_result;
+ }
+
+ // Backup required data we're going to override:
+ $child_api = $this->skin->api;
+ $child_success_message = $this->strings['process_success'];
+
+ // Override them
+ $this->skin->api = $api;
+ $this->strings['process_success_specific'] = $this->strings['parent_theme_install_success'];//, $api->name, $api->version);
+
+ $this->skin->feedback('parent_theme_prepare_install', $api->name, $api->version);
+
+ add_filter('install_theme_complete_actions', '__return_false', 999); // Don't show any actions after installing the theme.
+
+ // Install the parent theme
+ $parent_result = $this->run( array(
+ 'package' => $api->download_link,
+ 'destination' => get_theme_root(),
+ 'clear_destination' => false, //Do not overwrite files.
+ 'clear_working' => true
+ ) );
+
+ if ( is_wp_error($parent_result) )
+ add_filter('install_theme_complete_actions', array($this, 'hide_activate_preview_actions') );
+
+ // Start cleaning up after the parents installation
+ remove_filter('install_theme_complete_actions', '__return_false', 999);
+
+ // Reset child's result and data
+ $this->result = $child_result;
+ $this->skin->api = $child_api;
+ $this->strings['process_success'] = $child_success_message;
+
+ return $install_result;
+ }
+
+ /**
+ * Don't display the activate and preview actions to the user.
+ *
+ * Hooked to the {@see 'install_theme_complete_actions'} filter by
+ * Theme_Upgrader::check_parent_theme_filter() when installing
+ * a child theme and installing the parent theme fails.
+ *
+ * @since 3.4.0
+ * @access public
+ *
+ * @param array $actions Preview actions.
+ * @return array
+ */
+ public function hide_activate_preview_actions( $actions ) {
+ unset($actions['activate'], $actions['preview']);
+ return $actions;
+ }
+
+ /**
+ * Install a theme package.
+ *
+ * @since 2.8.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
+ *
+ * @param string $package The full local path or URI of the package.
+ * @param array $args {
+ * Optional. Other arguments for installing a theme package. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the updates cache if successful.
+ * Default true.
+ * }
+ *
+ * @return bool|WP_Error True if the install was successful, false or a WP_Error object otherwise.
+ */
+ public function install( $package, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->install_strings();
+
+ add_filter('upgrader_source_selection', array($this, 'check_package') );
+ add_filter('upgrader_post_install', array($this, 'check_parent_theme_filter'), 10, 3);
+ // Clear cache so wp_update_themes() knows about the new theme.
+ add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
+
+ $this->run( array(
+ 'package' => $package,
+ 'destination' => get_theme_root(),
+ 'clear_destination' => false, //Do not overwrite files.
+ 'clear_working' => true,
+ 'hook_extra' => array(
+ 'type' => 'theme',
+ 'action' => 'install',
+ ),
+ ) );
+
+ remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
+ remove_filter('upgrader_source_selection', array($this, 'check_package') );
+ remove_filter('upgrader_post_install', array($this, 'check_parent_theme_filter'));
+
+ if ( ! $this->result || is_wp_error($this->result) )
+ return $this->result;
+
+ // Refresh the Theme Update information
+ wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
+
+ return true;
+ }
+
+ /**
+ * Upgrade a theme.
+ *
+ * @since 2.8.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
+ *
+ * @param string $theme The theme slug.
+ * @param array $args {
+ * Optional. Other arguments for upgrading a theme. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the update cache if successful.
+ * Default true.
+ * }
+ * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise.
+ */
+ public function upgrade( $theme, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->upgrade_strings();
+
+ // Is an update available?
+ $current = get_site_transient( 'update_themes' );
+ if ( !isset( $current->response[ $theme ] ) ) {
+ $this->skin->before();
+ $this->skin->set_result(false);
+ $this->skin->error( 'up_to_date' );
+ $this->skin->after();
+ return false;
+ }
+
+ $r = $current->response[ $theme ];
+
+ add_filter('upgrader_pre_install', array($this, 'current_before'), 10, 2);
+ add_filter('upgrader_post_install', array($this, 'current_after'), 10, 2);
+ add_filter('upgrader_clear_destination', array($this, 'delete_old_theme'), 10, 4);
+ // Clear cache so wp_update_themes() knows about the new theme.
+ add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
+
+ $this->run( array(
+ 'package' => $r['package'],
+ 'destination' => get_theme_root( $theme ),
+ 'clear_destination' => true,
+ 'clear_working' => true,
+ 'hook_extra' => array(
+ 'theme' => $theme,
+ 'type' => 'theme',
+ 'action' => 'update',
+ ),
+ ) );
+
+ remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
+ remove_filter('upgrader_pre_install', array($this, 'current_before'));
+ remove_filter('upgrader_post_install', array($this, 'current_after'));
+ remove_filter('upgrader_clear_destination', array($this, 'delete_old_theme'));
+
+ if ( ! $this->result || is_wp_error($this->result) )
+ return $this->result;
+
+ wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
+
+ return true;
+ }
+
+ /**
+ * Upgrade several themes at once.
+ *
+ * @since 3.0.0
+ * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
+ *
+ * @param array $themes The theme slugs.
+ * @param array $args {
+ * Optional. Other arguments for upgrading several themes at once. Default empty array.
+ *
+ * @type bool $clear_update_cache Whether to clear the update cache if successful.
+ * Default true.
+ * }
+ * @return array[]|false An array of results, or false if unable to connect to the filesystem.
+ */
+ public function bulk_upgrade( $themes, $args = array() ) {
+
+ $defaults = array(
+ 'clear_update_cache' => true,
+ );
+ $parsed_args = wp_parse_args( $args, $defaults );
+
+ $this->init();
+ $this->bulk = true;
+ $this->upgrade_strings();
+
+ $current = get_site_transient( 'update_themes' );
+
+ add_filter('upgrader_pre_install', array($this, 'current_before'), 10, 2);
+ add_filter('upgrader_post_install', array($this, 'current_after'), 10, 2);
+ add_filter('upgrader_clear_destination', array($this, 'delete_old_theme'), 10, 4);
+ // Clear cache so wp_update_themes() knows about the new theme.
+ add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
+
+ $this->skin->header();
+
+ // Connect to the Filesystem first.
+ $res = $this->fs_connect( array(WP_CONTENT_DIR) );
+ if ( ! $res ) {
+ $this->skin->footer();
+ return false;
+ }
+
+ $this->skin->bulk_header();
+
+ // Only start maintenance mode if:
+ // - running Multisite and there are one or more themes specified, OR
+ // - a theme with an update available is currently in use.
+ // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
+ $maintenance = ( is_multisite() && ! empty( $themes ) );
+ foreach ( $themes as $theme )
+ $maintenance = $maintenance || $theme == get_stylesheet() || $theme == get_template();
+ if ( $maintenance )
+ $this->maintenance_mode(true);
+
+ $results = array();
+
+ $this->update_count = count($themes);
+ $this->update_current = 0;
+ foreach ( $themes as $theme ) {
+ $this->update_current++;
+
+ $this->skin->theme_info = $this->theme_info($theme);
+
+ if ( !isset( $current->response[ $theme ] ) ) {
+ $this->skin->set_result(true);
+ $this->skin->before();
+ $this->skin->feedback( 'up_to_date' );
+ $this->skin->after();
+ $results[$theme] = true;
+ continue;
+ }
+
+ // Get the URL to the zip file
+ $r = $current->response[ $theme ];
+
+ $result = $this->run( array(
+ 'package' => $r['package'],
+ 'destination' => get_theme_root( $theme ),
+ 'clear_destination' => true,
+ 'clear_working' => true,
+ 'is_multi' => true,
+ 'hook_extra' => array(
+ 'theme' => $theme
+ ),
+ ) );
+
+ $results[$theme] = $this->result;
+
+ // Prevent credentials auth screen from displaying multiple times
+ if ( false === $result )
+ break;
+ } //end foreach $plugins
+
+ $this->maintenance_mode(false);
+
+ /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
+ do_action( 'upgrader_process_complete', $this, array(
+ 'action' => 'update',
+ 'type' => 'theme',
+ 'bulk' => true,
+ 'themes' => $themes,
+ ) );
+
+ $this->skin->bulk_footer();
+
+ $this->skin->footer();
+
+ // Cleanup our hooks, in case something else does a upgrade on this connection.
+ remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
+ remove_filter('upgrader_pre_install', array($this, 'current_before'));
+ remove_filter('upgrader_post_install', array($this, 'current_after'));
+ remove_filter('upgrader_clear_destination', array($this, 'delete_old_theme'));
+
+ // Refresh the Theme Update information
+ wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
+
+ return $results;
+ }
+
+ /**
+ * Check that the package source contains a valid theme.
+ *
+ * Hooked to the {@see 'upgrader_source_selection'} filter by Theme_Upgrader::install().
+ * It will return an error if the theme doesn't have style.css or index.php
+ * files.
+ *
+ * @since 3.3.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param string $source The full path to the package source.
+ * @return string|WP_Error The source or a WP_Error.
+ */
+ public function check_package( $source ) {
+ global $wp_filesystem;
+
+ if ( is_wp_error($source) )
+ return $source;
+
+ // Check the folder contains a valid theme
+ $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source);
+ if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, let's not prevent installation.
+ return $source;
+
+ // A proper archive should have a style.css file in the single subdirectory
+ if ( ! file_exists( $working_directory . 'style.css' ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_style', $this->strings['incompatible_archive'],
+ /* translators: %s: style.css */
+ sprintf( __( 'The theme is missing the %s stylesheet.' ),
+ 'style.css
'
+ )
+ );
+ }
+
+ $info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) );
+
+ if ( empty( $info['Name'] ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_name', $this->strings['incompatible_archive'],
+ /* translators: %s: style.css */
+ sprintf( __( 'The %s stylesheet doesn’t contain a valid theme header.' ),
+ 'style.css
'
+ )
+ );
+ }
+
+ // If it's not a child theme, it must have at least an index.php to be legit.
+ if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_index', $this->strings['incompatible_archive'],
+ /* translators: %s: index.php */
+ sprintf( __( 'The theme is missing the %s file.' ),
+ 'index.php
'
+ )
+ );
+ }
+
+ return $source;
+ }
+
+ /**
+ * Turn on maintenance mode before attempting to upgrade the current theme.
+ *
+ * Hooked to the {@see 'upgrader_pre_install'} filter by Theme_Upgrader::upgrade() and
+ * Theme_Upgrader::bulk_upgrade().
+ *
+ * @since 2.8.0
+ * @access public
+ *
+ * @param bool|WP_Error $return
+ * @param array $theme
+ * @return bool|WP_Error
+ */
+ public function current_before($return, $theme) {
+ if ( is_wp_error($return) )
+ return $return;
+
+ $theme = isset($theme['theme']) ? $theme['theme'] : '';
+
+ if ( $theme != get_stylesheet() ) //If not current
+ return $return;
+ //Change to maintenance mode now.
+ if ( ! $this->bulk )
+ $this->maintenance_mode(true);
+
+ return $return;
+ }
+
+ /**
+ * Turn off maintenance mode after upgrading the current theme.
+ *
+ * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::upgrade()
+ * and Theme_Upgrader::bulk_upgrade().
+ *
+ * @since 2.8.0
+ * @access public
+ *
+ * @param bool|WP_Error $return
+ * @param array $theme
+ * @return bool|WP_Error
+ */
+ public function current_after($return, $theme) {
+ if ( is_wp_error($return) )
+ return $return;
+
+ $theme = isset($theme['theme']) ? $theme['theme'] : '';
+
+ if ( $theme != get_stylesheet() ) // If not current
+ return $return;
+
+ // Ensure stylesheet name hasn't changed after the upgrade:
+ if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {
+ wp_clean_themes_cache();
+ $stylesheet = $this->result['destination_name'];
+ switch_theme( $stylesheet );
+ }
+
+ //Time to remove maintenance mode
+ if ( ! $this->bulk )
+ $this->maintenance_mode(false);
+ return $return;
+ }
+
+ /**
+ * Delete the old theme during an upgrade.
+ *
+ * Hooked to the {@see 'upgrader_clear_destination'} filter by Theme_Upgrader::upgrade()
+ * and Theme_Upgrader::bulk_upgrade().
+ *
+ * @since 2.8.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param bool $removed
+ * @param string $local_destination
+ * @param string $remote_destination
+ * @param array $theme
+ * @return bool
+ */
+ public function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) {
+ global $wp_filesystem;
+
+ if ( is_wp_error( $removed ) )
+ return $removed; // Pass errors through.
+
+ if ( ! isset( $theme['theme'] ) )
+ return $removed;
+
+ $theme = $theme['theme'];
+ $themes_dir = trailingslashit( $wp_filesystem->wp_themes_dir( $theme ) );
+ if ( $wp_filesystem->exists( $themes_dir . $theme ) ) {
+ if ( ! $wp_filesystem->delete( $themes_dir . $theme, true ) )
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the WP_Theme object for a theme.
+ *
+ * @since 2.8.0
+ * @since 3.0.0 The `$theme` argument was added.
+ * @access public
+ *
+ * @param string $theme The directory name of the theme. This is optional, and if not supplied,
+ * the directory name from the last result will be used.
+ * @return WP_Theme|false The theme's info object, or false `$theme` is not supplied
+ * and the last result isn't set.
+ */
+ public function theme_info($theme = null) {
+
+ if ( empty($theme) ) {
+ if ( !empty($this->result['destination_name']) )
+ $theme = $this->result['destination_name'];
+ else
+ return false;
+ }
+ return wp_get_theme( $theme );
+ }
+
+}
diff --git a/wp-admin/includes/class-walker-nav-menu-edit.php b/wp-admin/includes/class-walker-nav-menu-edit.php
index 7576de12..9a2f3ecb 100644
--- a/wp-admin/includes/class-walker-nav-menu-edit.php
+++ b/wp-admin/includes/class-walker-nav-menu-edit.php
@@ -70,7 +70,7 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
'_wpnonce',
);
- $original_title = '';
+ $original_title = false;
if ( 'taxonomy' == $item->type ) {
$original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' );
if ( is_wp_error( $original_title ) )
diff --git a/wp-admin/includes/class-wp-ajax-upgrader-skin.php b/wp-admin/includes/class-wp-ajax-upgrader-skin.php
new file mode 100644
index 00000000..8698e204
--- /dev/null
+++ b/wp-admin/includes/class-wp-ajax-upgrader-skin.php
@@ -0,0 +1,132 @@
+errors = new WP_Error();
+ }
+
+ /**
+ * Retrieves the list of errors.
+ *
+ * @since 4.6.0
+ * @access public
+ *
+ * @return WP_Error Errors during an upgrade.
+ */
+ public function get_errors() {
+ return $this->errors;
+ }
+
+ /**
+ * Retrieves a string for error messages.
+ *
+ * @since 4.6.0
+ * @access public
+ *
+ * @return string Error messages during an upgrade.
+ */
+ public function get_error_messages() {
+ $messages = array();
+
+ foreach ( $this->errors->get_error_codes() as $error_code ) {
+ if ( $this->errors->get_error_data( $error_code ) && is_string( $this->errors->get_error_data( $error_code ) ) ) {
+ $messages[] = $this->errors->get_error_message( $error_code ) . ' ' . esc_html( strip_tags( $this->errors->get_error_data( $error_code ) ) );
+ } else {
+ $messages[] = $this->errors->get_error_message( $error_code );
+ }
+ }
+
+ return implode( ', ', $messages );
+ }
+
+ /**
+ * Stores a log entry for an error.
+ *
+ * @since 4.6.0
+ * @access public
+ *
+ * @param string|WP_Error $errors Errors.
+ */
+ public function error( $errors ) {
+ if ( is_string( $errors ) ) {
+ $string = $errors;
+ if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
+ $string = $this->upgrader->strings[ $string ];
+ }
+
+ if ( false !== strpos( $string, '%' ) ) {
+ $args = func_get_args();
+ $args = array_splice( $args, 1 );
+ if ( ! empty( $args ) ) {
+ $string = vsprintf( $string, $args );
+ }
+ }
+
+ // Count existing errors to generate an unique error code.
+ $errors_count = count( $errors->get_error_codes() );
+ $this->errors->add( 'unknown_upgrade_error_' . $errors_count + 1 , $string );
+ } elseif ( is_wp_error( $errors ) ) {
+ foreach ( $errors->get_error_codes() as $error_code ) {
+ $this->errors->add( $error_code, $errors->get_error_message( $error_code ), $errors->get_error_data( $error_code ) );
+ }
+ }
+
+ $args = func_get_args();
+ call_user_func_array( array( $this, 'parent::error' ), $args );
+ }
+
+ /**
+ * Stores a log entry.
+ *
+ * @since 4.6.0
+ * @access public
+ *
+ * @param string|array|WP_Error $data Log entry data.
+ */
+ public function feedback( $data ) {
+ if ( is_wp_error( $data ) ) {
+ foreach ( $data->get_error_codes() as $error_code ) {
+ $this->errors->add( $error_code, $data->get_error_message( $error_code ), $data->get_error_data( $error_code ) );
+ }
+ }
+
+ $args = func_get_args();
+ call_user_func_array( array( $this, 'parent::feedback' ), $args );
+ }
+}
diff --git a/wp-admin/includes/class-wp-automatic-updater.php b/wp-admin/includes/class-wp-automatic-updater.php
new file mode 100644
index 00000000..12199394
--- /dev/null
+++ b/wp-admin/includes/class-wp-automatic-updater.php
@@ -0,0 +1,932 @@
+is_disabled() )
+ return false;
+
+ // Only relax the filesystem checks when the update doesn't include new files
+ $allow_relaxed_file_ownership = false;
+ if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
+ $allow_relaxed_file_ownership = true;
+ }
+
+ // If we can't do an auto core update, we may still be able to email the user.
+ if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) {
+ if ( 'core' == $type )
+ $this->send_core_update_notification_email( $item );
+ return false;
+ }
+
+ // Next up, is this an item we can update?
+ if ( 'core' == $type )
+ $update = Core_Upgrader::should_update_to_version( $item->current );
+ else
+ $update = ! empty( $item->autoupdate );
+
+ /**
+ * Filters whether to automatically update core, a plugin, a theme, or a language.
+ *
+ * The dynamic portion of the hook name, `$type`, refers to the type of update
+ * being checked. Can be 'core', 'theme', 'plugin', or 'translation'.
+ *
+ * Generally speaking, plugins, themes, and major core versions are not updated
+ * by default, while translations and minor and development versions for core
+ * are updated by default.
+ *
+ * See the {@see 'allow_dev_auto_core_updates', {@see 'allow_minor_auto_core_updates'},
+ * and {@see 'allow_major_auto_core_updates'} filters for a more straightforward way to
+ * adjust core updates.
+ *
+ * @since 3.7.0
+ *
+ * @param bool $update Whether to update.
+ * @param object $item The update offer.
+ */
+ $update = apply_filters( 'auto_update_' . $type, $update, $item );
+
+ if ( ! $update ) {
+ if ( 'core' == $type )
+ $this->send_core_update_notification_email( $item );
+ return false;
+ }
+
+ // If it's a core update, are we actually compatible with its requirements?
+ if ( 'core' == $type ) {
+ global $wpdb;
+
+ $php_compat = version_compare( phpversion(), $item->php_version, '>=' );
+ if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) )
+ $mysql_compat = true;
+ else
+ $mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' );
+
+ if ( ! $php_compat || ! $mysql_compat )
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Notifies an administrator of a core update.
+ *
+ * @since 3.7.0
+ * @access protected
+ *
+ * @param object $item The update offer.
+ */
+ protected function send_core_update_notification_email( $item ) {
+ $notified = get_site_option( 'auto_core_update_notified' );
+
+ // Don't notify if we've already notified the same email address of the same version.
+ if ( $notified && $notified['email'] == get_site_option( 'admin_email' ) && $notified['version'] == $item->current )
+ return false;
+
+ // See if we need to notify users of a core update.
+ $notify = ! empty( $item->notify_email );
+
+ /**
+ * Filters whether to notify the site administrator of a new core update.
+ *
+ * By default, administrators are notified when the update offer received
+ * from WordPress.org sets a particular flag. This allows some discretion
+ * in if and when to notify.
+ *
+ * This filter is only evaluated once per release. If the same email address
+ * was already notified of the same new version, WordPress won't repeatedly
+ * email the administrator.
+ *
+ * This filter is also used on about.php to check if a plugin has disabled
+ * these notifications.
+ *
+ * @since 3.7.0
+ *
+ * @param bool $notify Whether the site administrator is notified.
+ * @param object $item The update offer.
+ */
+ if ( ! apply_filters( 'send_core_update_notification_email', $notify, $item ) )
+ return false;
+
+ $this->send_email( 'manual', $item );
+ return true;
+ }
+
+ /**
+ * Update an item, if appropriate.
+ *
+ * @since 3.7.0
+ * @access public
+ *
+ * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'.
+ * @param object $item The update offer.
+ *
+ * @return null|WP_Error
+ */
+ public function update( $type, $item ) {
+ $skin = new Automatic_Upgrader_Skin;
+
+ switch ( $type ) {
+ case 'core':
+ // The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter.
+ add_filter( 'update_feedback', array( $skin, 'feedback' ) );
+ $upgrader = new Core_Upgrader( $skin );
+ $context = ABSPATH;
+ break;
+ case 'plugin':
+ $upgrader = new Plugin_Upgrader( $skin );
+ $context = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR
+ break;
+ case 'theme':
+ $upgrader = new Theme_Upgrader( $skin );
+ $context = get_theme_root( $item->theme );
+ break;
+ case 'translation':
+ $upgrader = new Language_Pack_Upgrader( $skin );
+ $context = WP_CONTENT_DIR; // WP_LANG_DIR;
+ break;
+ }
+
+ // Determine whether we can and should perform this update.
+ if ( ! $this->should_update( $type, $item, $context ) )
+ return false;
+
+ /**
+ * Fires immediately prior to an auto-update.
+ *
+ * @since 4.4.0
+ *
+ * @param string $type The type of update being checked: 'core', 'theme', 'plugin', or 'translation'.
+ * @param object $item The update offer.
+ * @param string $context The filesystem context (a path) against which filesystem access and status
+ * should be checked.
+ */
+ do_action( 'pre_auto_update', $type, $item, $context );
+
+ $upgrader_item = $item;
+ switch ( $type ) {
+ case 'core':
+ $skin->feedback( __( 'Updating to WordPress %s' ), $item->version );
+ $item_name = sprintf( __( 'WordPress %s' ), $item->version );
+ break;
+ case 'theme':
+ $upgrader_item = $item->theme;
+ $theme = wp_get_theme( $upgrader_item );
+ $item_name = $theme->Get( 'Name' );
+ $skin->feedback( __( 'Updating theme: %s' ), $item_name );
+ break;
+ case 'plugin':
+ $upgrader_item = $item->plugin;
+ $plugin_data = get_plugin_data( $context . '/' . $upgrader_item );
+ $item_name = $plugin_data['Name'];
+ $skin->feedback( __( 'Updating plugin: %s' ), $item_name );
+ break;
+ case 'translation':
+ $language_item_name = $upgrader->get_name_for_update( $item );
+ $item_name = sprintf( __( 'Translations for %s' ), $language_item_name );
+ $skin->feedback( sprintf( __( 'Updating translations for %1$s (%2$s)…' ), $language_item_name, $item->language ) );
+ break;
+ }
+
+ $allow_relaxed_file_ownership = false;
+ if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
+ $allow_relaxed_file_ownership = true;
+ }
+
+ // Boom, This sites about to get a whole new splash of paint!
+ $upgrade_result = $upgrader->upgrade( $upgrader_item, array(
+ 'clear_update_cache' => false,
+ // Always use partial builds if possible for core updates.
+ 'pre_check_md5' => false,
+ // Only available for core updates.
+ 'attempt_rollback' => true,
+ // Allow relaxed file ownership in some scenarios
+ 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
+ ) );
+
+ // If the filesystem is unavailable, false is returned.
+ if ( false === $upgrade_result ) {
+ $upgrade_result = new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
+ }
+
+ if ( 'core' == $type ) {
+ if ( is_wp_error( $upgrade_result ) && ( 'up_to_date' == $upgrade_result->get_error_code() || 'locked' == $upgrade_result->get_error_code() ) ) {
+ // These aren't actual errors, treat it as a skipped-update instead to avoid triggering the post-core update failure routines.
+ return false;
+ }
+
+ // Core doesn't output this, so let's append it so we don't get confused.
+ if ( is_wp_error( $upgrade_result ) ) {
+ $skin->error( __( 'Installation Failed' ), $upgrade_result );
+ } else {
+ $skin->feedback( __( 'WordPress updated successfully' ) );
+ }
+ }
+
+ $this->update_results[ $type ][] = (object) array(
+ 'item' => $item,
+ 'result' => $upgrade_result,
+ 'name' => $item_name,
+ 'messages' => $skin->get_upgrade_messages()
+ );
+
+ return $upgrade_result;
+ }
+
+ /**
+ * Kicks off the background update process, looping through all pending updates.
+ *
+ * @since 3.7.0
+ * @access public
+ *
+ * @global wpdb $wpdb
+ * @global string $wp_version
+ */
+ public function run() {
+ global $wpdb, $wp_version;
+
+ if ( $this->is_disabled() )
+ return;
+
+ if ( ! is_main_network() || ! is_main_site() )
+ return;
+
+ if ( ! WP_Upgrader::create_lock( 'auto_updater' ) )
+ return;
+
+ // Don't automatically run these thins, as we'll handle it ourselves
+ remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
+ remove_action( 'upgrader_process_complete', 'wp_version_check' );
+ remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
+ remove_action( 'upgrader_process_complete', 'wp_update_themes' );
+
+ // Next, Plugins
+ wp_update_plugins(); // Check for Plugin updates
+ $plugin_updates = get_site_transient( 'update_plugins' );
+ if ( $plugin_updates && !empty( $plugin_updates->response ) ) {
+ foreach ( $plugin_updates->response as $plugin ) {
+ $this->update( 'plugin', $plugin );
+ }
+ // Force refresh of plugin update information
+ wp_clean_plugins_cache();
+ }
+
+ // Next, those themes we all love
+ wp_update_themes(); // Check for Theme updates
+ $theme_updates = get_site_transient( 'update_themes' );
+ if ( $theme_updates && !empty( $theme_updates->response ) ) {
+ foreach ( $theme_updates->response as $theme ) {
+ $this->update( 'theme', (object) $theme );
+ }
+ // Force refresh of theme update information
+ wp_clean_themes_cache();
+ }
+
+ // Next, Process any core update
+ wp_version_check(); // Check for Core updates
+ $core_update = find_core_auto_update();
+
+ if ( $core_update )
+ $this->update( 'core', $core_update );
+
+ // Clean up, and check for any pending translations
+ // (Core_Upgrader checks for core updates)
+ $theme_stats = array();
+ if ( isset( $this->update_results['theme'] ) ) {
+ foreach ( $this->update_results['theme'] as $upgrade ) {
+ $theme_stats[ $upgrade->item->theme ] = ( true === $upgrade->result );
+ }
+ }
+ wp_update_themes( $theme_stats ); // Check for Theme updates
+
+ $plugin_stats = array();
+ if ( isset( $this->update_results['plugin'] ) ) {
+ foreach ( $this->update_results['plugin'] as $upgrade ) {
+ $plugin_stats[ $upgrade->item->plugin ] = ( true === $upgrade->result );
+ }
+ }
+ wp_update_plugins( $plugin_stats ); // Check for Plugin updates
+
+ // Finally, Process any new translations
+ $language_updates = wp_get_translation_updates();
+ if ( $language_updates ) {
+ foreach ( $language_updates as $update ) {
+ $this->update( 'translation', $update );
+ }
+
+ // Clear existing caches
+ wp_clean_update_cache();
+
+ wp_version_check(); // check for Core updates
+ wp_update_themes(); // Check for Theme updates
+ wp_update_plugins(); // Check for Plugin updates
+ }
+
+ // Send debugging email to all development installs.
+ if ( ! empty( $this->update_results ) ) {
+ $development_version = false !== strpos( $wp_version, '-' );
+
+ /**
+ * Filters whether to send a debugging email for each automatic background update.
+ *
+ * @since 3.7.0
+ *
+ * @param bool $development_version By default, emails are sent if the
+ * install is a development version.
+ * Return false to avoid the email.
+ */
+ if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) )
+ $this->send_debug_email();
+
+ if ( ! empty( $this->update_results['core'] ) )
+ $this->after_core_update( $this->update_results['core'][0] );
+
+ /**
+ * Fires after all automatic updates have run.
+ *
+ * @since 3.8.0
+ *
+ * @param array $update_results The results of all attempted updates.
+ */
+ do_action( 'automatic_updates_complete', $this->update_results );
+ }
+
+ WP_Upgrader::release_lock( 'auto_updater' );
+ }
+
+ /**
+ * If we tried to perform a core update, check if we should send an email,
+ * and if we need to avoid processing future updates.
+ *
+ * @since Unknown
+ * @access protected
+ *
+ * @global string $wp_version
+ *
+ * @param object $update_result The result of the core update. Includes the update offer and result.
+ */
+ protected function after_core_update( $update_result ) {
+ global $wp_version;
+
+ $core_update = $update_result->item;
+ $result = $update_result->result;
+
+ if ( ! is_wp_error( $result ) ) {
+ $this->send_email( 'success', $core_update );
+ return;
+ }
+
+ $error_code = $result->get_error_code();
+
+ // Any of these WP_Error codes are critical failures, as in they occurred after we started to copy core files.
+ // We should not try to perform a background update again until there is a successful one-click update performed by the user.
+ $critical = false;
+ if ( $error_code === 'disk_full' || false !== strpos( $error_code, '__copy_dir' ) ) {
+ $critical = true;
+ } elseif ( $error_code === 'rollback_was_required' && is_wp_error( $result->get_error_data()->rollback ) ) {
+ // A rollback is only critical if it failed too.
+ $critical = true;
+ $rollback_result = $result->get_error_data()->rollback;
+ } elseif ( false !== strpos( $error_code, 'do_rollback' ) ) {
+ $critical = true;
+ }
+
+ if ( $critical ) {
+ $critical_data = array(
+ 'attempted' => $core_update->current,
+ 'current' => $wp_version,
+ 'error_code' => $error_code,
+ 'error_data' => $result->get_error_data(),
+ 'timestamp' => time(),
+ 'critical' => true,
+ );
+ if ( isset( $rollback_result ) ) {
+ $critical_data['rollback_code'] = $rollback_result->get_error_code();
+ $critical_data['rollback_data'] = $rollback_result->get_error_data();
+ }
+ update_site_option( 'auto_core_update_failed', $critical_data );
+ $this->send_email( 'critical', $core_update, $result );
+ return;
+ }
+
+ /*
+ * Any other WP_Error code (like download_failed or files_not_writable) occurs before
+ * we tried to copy over core files. Thus, the failures are early and graceful.
+ *
+ * We should avoid trying to perform a background update again for the same version.
+ * But we can try again if another version is released.
+ *
+ * For certain 'transient' failures, like download_failed, we should allow retries.
+ * In fact, let's schedule a special update for an hour from now. (It's possible
+ * the issue could actually be on WordPress.org's side.) If that one fails, then email.
+ */
+ $send = true;
+ $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro', 'locked' );
+ if ( in_array( $error_code, $transient_failures ) && ! get_site_option( 'auto_core_update_failed' ) ) {
+ wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' );
+ $send = false;
+ }
+
+ $n = get_site_option( 'auto_core_update_notified' );
+ // Don't notify if we've already notified the same email address of the same version of the same notification type.
+ if ( $n && 'fail' == $n['type'] && $n['email'] == get_site_option( 'admin_email' ) && $n['version'] == $core_update->current )
+ $send = false;
+
+ update_site_option( 'auto_core_update_failed', array(
+ 'attempted' => $core_update->current,
+ 'current' => $wp_version,
+ 'error_code' => $error_code,
+ 'error_data' => $result->get_error_data(),
+ 'timestamp' => time(),
+ 'retry' => in_array( $error_code, $transient_failures ),
+ ) );
+
+ if ( $send )
+ $this->send_email( 'fail', $core_update, $result );
+ }
+
+ /**
+ * Sends an email upon the completion or failure of a background core update.
+ *
+ * @since 3.7.0
+ * @access protected
+ *
+ * @global string $wp_version
+ *
+ * @param string $type The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'.
+ * @param object $core_update The update offer that was attempted.
+ * @param mixed $result Optional. The result for the core update. Can be WP_Error.
+ */
+ protected function send_email( $type, $core_update, $result = null ) {
+ update_site_option( 'auto_core_update_notified', array(
+ 'type' => $type,
+ 'email' => get_site_option( 'admin_email' ),
+ 'version' => $core_update->current,
+ 'timestamp' => time(),
+ ) );
+
+ $next_user_core_update = get_preferred_from_update_core();
+ // If the update transient is empty, use the update we just performed
+ if ( ! $next_user_core_update )
+ $next_user_core_update = $core_update;
+ $newer_version_available = ( 'upgrade' == $next_user_core_update->response && version_compare( $next_user_core_update->version, $core_update->version, '>' ) );
+
+ /**
+ * Filters whether to send an email following an automatic background core update.
+ *
+ * @since 3.7.0
+ *
+ * @param bool $send Whether to send the email. Default true.
+ * @param string $type The type of email to send. Can be one of
+ * 'success', 'fail', 'critical'.
+ * @param object $core_update The update offer that was attempted.
+ * @param mixed $result The result for the core update. Can be WP_Error.
+ */
+ if ( 'manual' !== $type && ! apply_filters( 'auto_core_update_send_email', true, $type, $core_update, $result ) )
+ return;
+
+ switch ( $type ) {
+ case 'success' : // We updated.
+ /* translators: 1: Site name, 2: WordPress version number. */
+ $subject = __( '[%1$s] Your site has updated to WordPress %2$s' );
+ break;
+
+ case 'fail' : // We tried to update but couldn't.
+ case 'manual' : // We can't update (and made no attempt).
+ /* translators: 1: Site name, 2: WordPress version number. */
+ $subject = __( '[%1$s] WordPress %2$s is available. Please update!' );
+ break;
+
+ case 'critical' : // We tried to update, started to copy files, then things went wrong.
+ /* translators: 1: Site name. */
+ $subject = __( '[%1$s] URGENT: Your site may be down due to a failed update' );
+ break;
+
+ default :
+ return;
+ }
+
+ // If the auto update is not to the latest version, say that the current version of WP is available instead.
+ $version = 'success' === $type ? $core_update->current : $next_user_core_update->current;
+ $subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $version );
+
+ $body = '';
+
+ switch ( $type ) {
+ case 'success' :
+ $body .= sprintf( __( 'Howdy! Your site at %1$s has been updated automatically to WordPress %2$s.' ), home_url(), $core_update->current );
+ $body .= "\n\n";
+ if ( ! $newer_version_available )
+ $body .= __( 'No further action is needed on your part.' ) . ' ';
+
+ // Can only reference the About screen if their update was successful.
+ list( $about_version ) = explode( '-', $core_update->current, 2 );
+ $body .= sprintf( __( "For more on version %s, see the About WordPress screen:" ), $about_version );
+ $body .= "\n" . admin_url( 'about.php' );
+
+ if ( $newer_version_available ) {
+ $body .= "\n\n" . sprintf( __( 'WordPress %s is also now available.' ), $next_user_core_update->current ) . ' ';
+ $body .= __( 'Updating is easy and only takes a few moments:' );
+ $body .= "\n" . network_admin_url( 'update-core.php' );
+ }
+
+ break;
+
+ case 'fail' :
+ case 'manual' :
+ $body .= sprintf( __( 'Please update your site at %1$s to WordPress %2$s.' ), home_url(), $next_user_core_update->current );
+
+ $body .= "\n\n";
+
+ // Don't show this message if there is a newer version available.
+ // Potential for confusion, and also not useful for them to know at this point.
+ if ( 'fail' == $type && ! $newer_version_available )
+ $body .= __( 'We tried but were unable to update your site automatically.' ) . ' ';
+
+ $body .= __( 'Updating is easy and only takes a few moments:' );
+ $body .= "\n" . network_admin_url( 'update-core.php' );
+ break;
+
+ case 'critical' :
+ if ( $newer_version_available )
+ $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update WordPress to version %2$s.' ), home_url(), $core_update->current );
+ else
+ $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update to the latest version of WordPress, %2$s.' ), home_url(), $core_update->current );
+
+ $body .= "\n\n" . __( "This means your site may be offline or broken. Don't panic; this can be fixed." );
+
+ $body .= "\n\n" . __( "Please check out your site now. It's possible that everything is working. If it says you need to update, you should do so:" );
+ $body .= "\n" . network_admin_url( 'update-core.php' );
+ break;
+ }
+
+ $critical_support = 'critical' === $type && ! empty( $core_update->support_email );
+ if ( $critical_support ) {
+ // Support offer if available.
+ $body .= "\n\n" . sprintf( __( "The WordPress team is willing to help you. Forward this email to %s and the team will work with you to make sure your site is working." ), $core_update->support_email );
+ } else {
+ // Add a note about the support forums.
+ $body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
+ $body .= "\n" . __( 'https://wordpress.org/support/' );
+ }
+
+ // Updates are important!
+ if ( $type != 'success' || $newer_version_available ) {
+ $body .= "\n\n" . __( 'Keeping your site updated is important for security. It also makes the internet a safer place for you and your readers.' );
+ }
+
+ if ( $critical_support ) {
+ $body .= " " . __( "If you reach out to us, we'll also ensure you'll never have this problem again." );
+ }
+
+ // If things are successful and we're now on the latest, mention plugins and themes if any are out of date.
+ if ( $type == 'success' && ! $newer_version_available && ( get_plugin_updates() || get_theme_updates() ) ) {
+ $body .= "\n\n" . __( 'You also have some plugins or themes with updates available. Update them now:' );
+ $body .= "\n" . network_admin_url();
+ }
+
+ $body .= "\n\n" . __( 'The WordPress Team' ) . "\n";
+
+ if ( 'critical' == $type && is_wp_error( $result ) ) {
+ $body .= "\n***\n\n";
+ $body .= sprintf( __( 'Your site was running version %s.' ), $GLOBALS['wp_version'] );
+ $body .= ' ' . __( 'We have some data that describes the error your site encountered.' );
+ $body .= ' ' . __( 'Your hosting company, support forum volunteers, or a friendly developer may be able to use this information to help you:' );
+
+ // If we had a rollback and we're still critical, then the rollback failed too.
+ // Loop through all errors (the main WP_Error, the update result, the rollback result) for code, data, etc.
+ if ( 'rollback_was_required' == $result->get_error_code() )
+ $errors = array( $result, $result->get_error_data()->update, $result->get_error_data()->rollback );
+ else
+ $errors = array( $result );
+
+ foreach ( $errors as $error ) {
+ if ( ! is_wp_error( $error ) )
+ continue;
+ $error_code = $error->get_error_code();
+ $body .= "\n\n" . sprintf( __( "Error code: %s" ), $error_code );
+ if ( 'rollback_was_required' == $error_code )
+ continue;
+ if ( $error->get_error_message() )
+ $body .= "\n" . $error->get_error_message();
+ $error_data = $error->get_error_data();
+ if ( $error_data )
+ $body .= "\n" . implode( ', ', (array) $error_data );
+ }
+ $body .= "\n";
+ }
+
+ $to = get_site_option( 'admin_email' );
+ $headers = '';
+
+ $email = compact( 'to', 'subject', 'body', 'headers' );
+
+ /**
+ * Filters the email sent following an automatic background core update.
+ *
+ * @since 3.7.0
+ *
+ * @param array $email {
+ * Array of email arguments that will be passed to wp_mail().
+ *
+ * @type string $to The email recipient. An array of emails
+ * can be returned, as handled by wp_mail().
+ * @type string $subject The email's subject.
+ * @type string $body The email message body.
+ * @type string $headers Any email headers, defaults to no headers.
+ * }
+ * @param string $type The type of email being sent. Can be one of
+ * 'success', 'fail', 'manual', 'critical'.
+ * @param object $core_update The update offer that was attempted.
+ * @param mixed $result The result for the core update. Can be WP_Error.
+ */
+ $email = apply_filters( 'auto_core_update_email', $email, $type, $core_update, $result );
+
+ wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
+ }
+
+ /**
+ * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
+ *
+ * @since 3.7.0
+ * @access protected
+ */
+ protected function send_debug_email() {
+ $update_count = 0;
+ foreach ( $this->update_results as $type => $updates )
+ $update_count += count( $updates );
+
+ $body = array();
+ $failures = 0;
+
+ $body[] = sprintf( __( 'WordPress site: %s' ), network_home_url( '/' ) );
+
+ // Core
+ if ( isset( $this->update_results['core'] ) ) {
+ $result = $this->update_results['core'][0];
+ if ( $result->result && ! is_wp_error( $result->result ) ) {
+ $body[] = sprintf( __( 'SUCCESS: WordPress was successfully updated to %s' ), $result->name );
+ } else {
+ $body[] = sprintf( __( 'FAILED: WordPress failed to update to %s' ), $result->name );
+ $failures++;
+ }
+ $body[] = '';
+ }
+
+ // Plugins, Themes, Translations
+ foreach ( array( 'plugin', 'theme', 'translation' ) as $type ) {
+ if ( ! isset( $this->update_results[ $type ] ) )
+ continue;
+ $success_items = wp_list_filter( $this->update_results[ $type ], array( 'result' => true ) );
+ if ( $success_items ) {
+ $messages = array(
+ 'plugin' => __( 'The following plugins were successfully updated:' ),
+ 'theme' => __( 'The following themes were successfully updated:' ),
+ 'translation' => __( 'The following translations were successfully updated:' ),
+ );
+
+ $body[] = $messages[ $type ];
+ foreach ( wp_list_pluck( $success_items, 'name' ) as $name ) {
+ $body[] = ' * ' . sprintf( __( 'SUCCESS: %s' ), $name );
+ }
+ }
+ if ( $success_items != $this->update_results[ $type ] ) {
+ // Failed updates
+ $messages = array(
+ 'plugin' => __( 'The following plugins failed to update:' ),
+ 'theme' => __( 'The following themes failed to update:' ),
+ 'translation' => __( 'The following translations failed to update:' ),
+ );
+
+ $body[] = $messages[ $type ];
+ foreach ( $this->update_results[ $type ] as $item ) {
+ if ( ! $item->result || is_wp_error( $item->result ) ) {
+ $body[] = ' * ' . sprintf( __( 'FAILED: %s' ), $item->name );
+ $failures++;
+ }
+ }
+ }
+ $body[] = '';
+ }
+
+ $site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
+ if ( $failures ) {
+ $body[] = trim( __(
+"BETA TESTING?
+=============
+
+This debugging email is sent when you are using a development version of WordPress.
+
+If you think these failures might be due to a bug in WordPress, could you report it?
+ * Open a thread in the support forums: https://wordpress.org/support/forum/alphabeta
+ * Or, if you're comfortable writing a bug report: https://core.trac.wordpress.org/
+
+Thanks! -- The WordPress Team" ) );
+ $body[] = '';
+
+ $subject = sprintf( __( '[%s] There were failures during background updates' ), $site_title );
+ } else {
+ $subject = sprintf( __( '[%s] Background updates have finished' ), $site_title );
+ }
+
+ $body[] = trim( __(
+'UPDATE LOG
+==========' ) );
+ $body[] = '';
+
+ foreach ( array( 'core', 'plugin', 'theme', 'translation' ) as $type ) {
+ if ( ! isset( $this->update_results[ $type ] ) )
+ continue;
+ foreach ( $this->update_results[ $type ] as $update ) {
+ $body[] = $update->name;
+ $body[] = str_repeat( '-', strlen( $update->name ) );
+ foreach ( $update->messages as $message )
+ $body[] = " " . html_entity_decode( str_replace( '…', '...', $message ) );
+ if ( is_wp_error( $update->result ) ) {
+ $results = array( 'update' => $update->result );
+ // If we rolled back, we want to know an error that occurred then too.
+ if ( 'rollback_was_required' === $update->result->get_error_code() )
+ $results = (array) $update->result->get_error_data();
+ foreach ( $results as $result_type => $result ) {
+ if ( ! is_wp_error( $result ) )
+ continue;
+
+ if ( 'rollback' === $result_type ) {
+ /* translators: 1: Error code, 2: Error message. */
+ $body[] = ' ' . sprintf( __( 'Rollback Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
+ } else {
+ /* translators: 1: Error code, 2: Error message. */
+ $body[] = ' ' . sprintf( __( 'Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
+ }
+
+ if ( $result->get_error_data() )
+ $body[] = ' ' . implode( ', ', (array) $result->get_error_data() );
+ }
+ }
+ $body[] = '';
+ }
+ }
+
+ $email = array(
+ 'to' => get_site_option( 'admin_email' ),
+ 'subject' => $subject,
+ 'body' => implode( "\n", $body ),
+ 'headers' => ''
+ );
+
+ /**
+ * Filters the debug email that can be sent following an automatic
+ * background core update.
+ *
+ * @since 3.8.0
+ *
+ * @param array $email {
+ * Array of email arguments that will be passed to wp_mail().
+ *
+ * @type string $to The email recipient. An array of emails
+ * can be returned, as handled by wp_mail().
+ * @type string $subject Email subject.
+ * @type string $body Email message body.
+ * @type string $headers Any email headers. Default empty.
+ * }
+ * @param int $failures The number of failures encountered while upgrading.
+ * @param mixed $results The results of all attempted updates.
+ */
+ $email = apply_filters( 'automatic_updates_debug_email', $email, $failures, $this->update_results );
+
+ wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
+ }
+}
diff --git a/wp-admin/includes/class-wp-comments-list-table.php b/wp-admin/includes/class-wp-comments-list-table.php
index a5f96939..116a55e0 100644
--- a/wp-admin/includes/class-wp-comments-list-table.php
+++ b/wp-admin/includes/class-wp-comments-list-table.php
@@ -166,7 +166,7 @@ class WP_Comments_List_Table extends WP_List_Table {
public function get_per_page( $comment_status = 'all' ) {
$comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' );
/**
- * Filter the number of comments listed per page in the comments list table.
+ * Filters the number of comments listed per page in the comments list table.
*
* @since 2.6.0
*
@@ -201,8 +201,7 @@ class WP_Comments_List_Table extends WP_List_Table {
$status_links = array();
$num_comments = ( $post_id ) ? wp_count_comments( $post_id ) : wp_count_comments();
- //, number_format_i18n($num_comments->moderated) ), "" . number_format_i18n($num_comments->moderated) . ""),
- //, number_format_i18n($num_comments->spam) ), "" . number_format_i18n($num_comments->spam) . "")
+
$stati = array(
/* translators: %s: all comments count */
'all' => _nx_noop(
@@ -270,7 +269,7 @@ class WP_Comments_List_Table extends WP_List_Table {
}
/**
- * Filter the comment status links.
+ * Filters the comment status links.
*
* @since 2.5.0
*
@@ -330,7 +329,7 @@ class WP_Comments_List_Table extends WP_List_Table {
verbose = $echo;
return $this->abspath();
}
@@ -160,7 +161,7 @@ class WP_Filesystem_Base {
* @return string The location of the remote path.
*/
public function get_base_dir( $base = '.', $echo = false ) {
- _deprecated_function(__FUNCTION__, '2.7', 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' );
+ _deprecated_function(__FUNCTION__, '2.7.0', 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' );
$this->verbose = $echo;
return $this->abspath();
}
@@ -316,7 +317,7 @@ class WP_Filesystem_Base {
*
* From the PHP documentation page for fileperms().
*
- * @link http://docs.php.net/fileperms
+ * @link https://secure.php.net/manual/en/function.fileperms.php
*
* @access public
* @since 2.5.0
@@ -384,7 +385,7 @@ class WP_Filesystem_Base {
* Converts '-rw-r--r--' to 0644
* From "info at rvgate dot nl"'s comment on the PHP documentation for chmod()
*
- * @link http://docs.php.net/manual/en/function.chmod.php#49614
+ * @link https://secure.php.net/manual/en/function.chmod.php#49614
*
* @access public
* @since 2.5.0
diff --git a/wp-admin/includes/class-wp-filesystem-ftpext.php b/wp-admin/includes/class-wp-filesystem-ftpext.php
index e1202aed..f337c733 100644
--- a/wp-admin/includes/class-wp-filesystem-ftpext.php
+++ b/wp-admin/includes/class-wp-filesystem-ftpext.php
@@ -120,13 +120,13 @@ class WP_Filesystem_FTPext extends WP_Filesystem_Base {
unlink( $tempfile );
return false;
}
-
+
if ( ! @ftp_fget( $this->link, $temp, $file, FTP_BINARY ) ) {
fclose( $temp );
unlink( $tempfile );
return false;
}
-
+
fseek( $temp, 0 ); // Skip back to the start of the file being written to
$contents = '';
@@ -159,8 +159,11 @@ class WP_Filesystem_FTPext extends WP_Filesystem_Base {
public function put_contents($file, $contents, $mode = false ) {
$tempfile = wp_tempnam($file);
$temp = fopen( $tempfile, 'wb+' );
- if ( ! $temp )
+
+ if ( ! $temp ) {
+ unlink( $tempfile );
return false;
+ }
mbstring_binary_safe_encoding();
diff --git a/wp-admin/includes/class-wp-filesystem-ftpsockets.php b/wp-admin/includes/class-wp-filesystem-ftpsockets.php
index fe74d33c..ff0b8824 100644
--- a/wp-admin/includes/class-wp-filesystem-ftpsockets.php
+++ b/wp-admin/includes/class-wp-filesystem-ftpsockets.php
@@ -121,8 +121,10 @@ class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
$temp = wp_tempnam( $file );
- if ( ! $temphandle = fopen($temp, 'w+') )
+ if ( ! $temphandle = fopen( $temp, 'w+' ) ) {
+ unlink( $temp );
return false;
+ }
mbstring_binary_safe_encoding();
diff --git a/wp-admin/includes/class-wp-filesystem-ssh2.php b/wp-admin/includes/class-wp-filesystem-ssh2.php
index 70f81d05..158b5559 100644
--- a/wp-admin/includes/class-wp-filesystem-ssh2.php
+++ b/wp-admin/includes/class-wp-filesystem-ssh2.php
@@ -193,7 +193,8 @@ class WP_Filesystem_SSH2 extends WP_Filesystem_Base {
*
* @param string $command
* @param bool $returnbool
- * @return bool|string
+ * @return bool|string True on success, false on failure. String if the command was executed, `$returnbool`
+ * is false (default), and data from the resulting stream was retrieved.
*/
public function run_command( $command, $returnbool = false ) {
if ( ! $this->link )
@@ -330,10 +331,10 @@ class WP_Filesystem_SSH2 extends WP_Filesystem_Base {
*
* @access public
*
- * @param string $file Path to the file.
- * @param string|int $owner A user name or number.
- * @param bool $recursive Optional. If set True changes file owner recursivly. Defaults to False.
- * @return bool|string Returns true on success or false on failure.
+ * @param string $file Path to the file.
+ * @param string|int $owner A user name or number.
+ * @param bool $recursive Optional. If set True changes file owner recursivly. Default False.
+ * @return bool True on success or false on failure.
*/
public function chown( $file, $owner, $recursive = false ) {
if ( ! $this->exists($file) )
diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php
index 32d08839..ee0f9af5 100644
--- a/wp-admin/includes/class-wp-list-table.php
+++ b/wp-admin/includes/class-wp-list-table.php
@@ -123,10 +123,10 @@ class WP_List_Table {
* in the list table, e.g. 'posts'. Default empty.
* @type string $singular Singular label for an object being listed, e.g. 'post'.
* Default empty
- * @type bool $ajax Whether the list table supports AJAX. This includes loading
+ * @type bool $ajax Whether the list table supports Ajax. This includes loading
* and sorting data, for example. If true, the class will call
- * the {@see _js_vars()} method in the footer to provide variables
- * to any scripts handling AJAX events. Default false.
+ * the _js_vars() method in the footer to provide variables
+ * to any scripts handling Ajax events. Default false.
* @type string $screen String containing the hook name used to determine the current
* screen. If left null, the current screen will be automatically set.
* Default null.
@@ -166,7 +166,7 @@ class WP_List_Table {
}
/**
- * Make private properties readable for backwards compatibility.
+ * Make private properties readable for backward compatibility.
*
* @since 4.0.0
* @access public
@@ -181,7 +181,7 @@ class WP_List_Table {
}
/**
- * Make private properties settable for backwards compatibility.
+ * Make private properties settable for backward compatibility.
*
* @since 4.0.0
* @access public
@@ -197,7 +197,7 @@ class WP_List_Table {
}
/**
- * Make private properties checkable for backwards compatibility.
+ * Make private properties checkable for backward compatibility.
*
* @since 4.0.0
* @access public
@@ -212,7 +212,7 @@ class WP_List_Table {
}
/**
- * Make private properties un-settable for backwards compatibility.
+ * Make private properties un-settable for backward compatibility.
*
* @since 4.0.0
* @access public
@@ -226,7 +226,7 @@ class WP_List_Table {
}
/**
- * Make private/protected methods readable for backwards compatibility.
+ * Make private/protected methods readable for backward compatibility.
*
* @since 4.0.0
* @access public
@@ -335,13 +335,13 @@ class WP_List_Table {
}
/**
- * Display the search box.
+ * Displays the search box.
*
* @since 3.1.0
* @access public
*
- * @param string $text The search button text
- * @param string $input_id The search input id
+ * @param string $text The 'submit' button label.
+ * @param string $input_id ID attribute value for the search input field.
*/
public function search_box( $text, $input_id ) {
if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
@@ -359,9 +359,9 @@ class WP_List_Table {
echo '';
?>
- - - 'search-submit') ); ?> + + + 'search-submit' ) ); ?>
get_views(); /** - * Filter the list of available list table views. + * Filters the list of available list table views. * * The dynamic portion of the hook name, `$this->screen->id`, refers * to the ID of the current screen, usually a string. @@ -432,13 +432,13 @@ class WP_List_Table { * @access protected * * @param string $which The location of the bulk actions: 'top' or 'bottom'. - * This is designated as optional for backwards-compatibility. + * This is designated as optional for backward compatibility. */ protected function bulk_actions( $which = '' ) { if ( is_null( $this->_actions ) ) { $no_new_actions = $this->_actions = $this->get_bulk_actions(); /** - * Filter the list table Bulk Actions drop-down. + * Filters the list table Bulk Actions drop-down. * * The dynamic portion of the hook name, `$this->screen->id`, refers * to the ID of the current screen, usually a string. @@ -541,7 +541,7 @@ class WP_List_Table { global $wpdb, $wp_locale; /** - * Filter whether to remove the 'Months' drop-down from the post list table. + * Filters whether to remove the 'Months' drop-down from the post list table. * * @since 4.2.0 * @@ -568,7 +568,7 @@ class WP_List_Table { ", $post_type ) ); /** - * Filter the 'Months' drop-down results. + * Filters the 'Months' drop-down results. * * @since 3.7.0 * @@ -721,7 +721,7 @@ class WP_List_Table { $per_page = $default; /** - * Filter the number of items to be displayed on each page of the list table. + * Filters the number of items to be displayed on each page of the list table. * * The dynamic hook name, $option, refers to the `per_page` option depending * on the type of list table in use. Possible values include: 'edit_comments_per_page', @@ -763,15 +763,16 @@ class WP_List_Table { $output = ' '; $current = $this->get_pagenum(); + $removable_query_args = wp_removable_query_args(); $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); - $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url ); + $current_url = remove_query_arg( $removable_query_args, $current_url ); $page_links = array(); $total_pages_before = ''; - $total_pages_after = ''; + $total_pages_after = ''; $disable_first = $disable_last = $disable_prev = $disable_next = false; @@ -812,9 +813,9 @@ class WP_List_Table { if ( 'bottom' === $which ) { $html_current_page = $current; - $total_pages_before = '' . __( 'Current Page' ) . ''; + $total_pages_before = '' . __( 'Current Page' ) . ''; } else { - $html_current_page = sprintf( "%s", + $html_current_page = sprintf( "%s", '', $current, strlen( $total_pages ) @@ -951,7 +952,7 @@ class WP_List_Table { } /** - * Filter the name of the primary column for the current list table. + * Filters the name of the primary column for the current list table. * * @since 4.3.0 * @@ -993,7 +994,7 @@ class WP_List_Table { $sortable_columns = $this->get_sortable_columns(); /** - * Filter the list table sortable columns for a specific screen. + * Filters the list table sortable columns for a specific screen. * * The dynamic portion of the hook name, `$this->screen->id`, refers * to the ID of the current screen, usually a string. diff --git a/wp-admin/includes/class-wp-media-list-table.php b/wp-admin/includes/class-wp-media-list-table.php index 82894740..170ec5a2 100644 --- a/wp-admin/includes/class-wp-media-list-table.php +++ b/wp-admin/includes/class-wp-media-list-table.php @@ -282,7 +282,7 @@ class WP_Media_List_Table extends WP_List_Table { $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); /** - * Filter the taxonomy columns for attachments in the Media list table. + * Filters the taxonomy columns for attachments in the Media list table. * * @since 3.5.0 * @@ -312,7 +312,7 @@ class WP_Media_List_Table extends WP_List_Table { /* translators: column name */ $posts_columns['date'] = _x( 'Date', 'column name' ); /** - * Filter the Media list table columns. + * Filters the Media list table columns. * * @since 2.5.0 * @@ -476,16 +476,18 @@ class WP_Media_List_Table extends WP_List_Table { if ( $parent ) { $title = _draft_or_post_title( $post->post_parent ); $parent_type = get_post_type_object( $parent->post_type ); + + if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { +?> + + post_parent ) ) { ?> - - show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { ?> - - -+ + + 'search-submit' ) ); ?> +
+ ' . __( 'Network Deactivate' ) . ''; + $actions['deactivate'] = '' . __( 'Network Deactivate' ) . ''; } } else { if ( current_user_can( 'manage_network_plugins' ) ) { /* translators: %s: plugin name */ - $actions['activate'] = '' . __( 'Network Activate' ) . ''; + $actions['activate'] = '' . __( 'Network Activate' ) . ''; } if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { /* translators: %s: plugin name */ - $actions['delete'] = '' . __( 'Delete' ) . ''; + $actions['delete'] = '' . __( 'Delete' ) . ''; } } } else { @@ -583,14 +623,14 @@ class WP_Plugins_List_Table extends WP_List_Table { ); } elseif ( $is_active ) { /* translators: %s: plugin name */ - $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; + $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; } else { /* translators: %s: plugin name */ - $actions['activate'] = '' . __( 'Activate' ) . ''; + $actions['activate'] = '' . __( 'Activate' ) . ''; if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) { /* translators: %s: plugin name */ - $actions['delete'] = '' . __( 'Delete' ) . ''; + $actions['delete'] = '' . __( 'Delete' ) . ''; } } // end if $is_active @@ -607,7 +647,7 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( $screen->in_admin( 'network' ) ) { /** - * Filter the action links displayed for each plugin in the Network Admin Plugins list table. + * Filters the action links displayed for each plugin in the Network Admin Plugins list table. * * The default action links for the Network plugins list table include * 'Network Activate', 'Network Deactivate', 'Edit', and 'Delete'. @@ -625,7 +665,7 @@ class WP_Plugins_List_Table extends WP_List_Table { $actions = apply_filters( 'network_admin_plugin_action_links', $actions, $plugin_file, $plugin_data, $context ); /** - * Filter the list of action links displayed for a specific plugin in the Network Admin Plugins list table. + * Filters the list of action links displayed for a specific plugin in the Network Admin Plugins list table. * * The dynamic portion of the hook name, $plugin_file, refers to the path * to the plugin file, relative to the plugins directory. @@ -645,7 +685,7 @@ class WP_Plugins_List_Table extends WP_List_Table { } else { /** - * Filter the action links displayed for each plugin in the Plugins list table. + * Filters the action links displayed for each plugin in the Plugins list table. * * The default action links for the site plugins list table include * 'Activate', 'Deactivate', and 'Edit', for a network site, and @@ -664,7 +704,7 @@ class WP_Plugins_List_Table extends WP_List_Table { $actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context ); /** - * Filter the list of action links displayed for a specific plugin in the Plugins list table. + * Filters the list of action links displayed for a specific plugin in the Plugins list table. * * The dynamic portion of the hook name, $plugin_file, refers to the path * to the plugin file, relative to the plugins directory. @@ -757,7 +797,7 @@ class WP_Plugins_List_Table extends WP_List_Table { } /** - * Filter the array of row meta for each plugin in the Plugins list table. + * Filters the array of row meta for each plugin in the Plugins list table. * * @since 2.8.0 * @@ -776,7 +816,7 @@ class WP_Plugins_List_Table extends WP_List_Table { echo ""; break; default: - $classes = "$column_name column-$column_name$class"; + $classes = "$column_name column-$column_name $class"; echo "$string
\n"; - } - - /** - * @access public - */ - public function header() { - // Nothing, This will be displayed within a iframe. - } - - /** - * @access public - */ - public function footer() { - // Nothing, This will be displayed within a iframe. - } - - /** - * - * @param string|WP_Error $error - */ - public function error($error) { - if ( is_string($error) && isset( $this->upgrader->strings[$error] ) ) - $this->error = $this->upgrader->strings[$error]; - - if ( is_wp_error($error) ) { - $messages = array(); - foreach ( $error->get_error_messages() as $emessage ) { - if ( $error->get_error_data() && is_string( $error->get_error_data() ) ) - $messages[] = $emessage . ' ' . esc_html( strip_tags( $error->get_error_data() ) ); - else - $messages[] = $emessage; - } - $this->error = implode(', ', $messages); - } - echo ''; - } - - /** - * @access public - */ - public function bulk_header() { - $this->feedback('skin_upgrade_start'); - } - - /** - * @access public - */ - public function bulk_footer() { - $this->feedback('skin_upgrade_end'); - } - - /** - * - * @param string $title - */ - public function before($title = '') { - $this->in_loop = true; - printf( '' . sprintf($this->upgrader->strings['skin_update_failed_error'], $title, '' . $this->error . '' ) . '
' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '
' . sprintf($this->upgrader->strings['skin_update_successful'], $title, 'jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').toggle();jQuery(\'span\', this).toggle(); return false;') . '
style.css
'
- )
- );
- }
-
- $info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) );
-
- if ( empty( $info['Name'] ) ) {
- return new WP_Error( 'incompatible_archive_theme_no_name', $this->strings['incompatible_archive'],
- /* translators: %s: style.css */
- sprintf( __( 'The %s stylesheet doesn’t contain a valid theme header.' ),
- 'style.css
'
- )
- );
- }
-
- // If it's not a child theme, it must have at least an index.php to be legit.
- if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) ) {
- return new WP_Error( 'incompatible_archive_theme_no_index', $this->strings['incompatible_archive'],
- /* translators: %s: index.php */
- sprintf( __( 'The theme is missing the %s file.' ),
- 'index.php
'
- )
- );
- }
-
- return $source;
- }
-
- /**
- * Turn on maintenance mode before attempting to upgrade the current theme.
- *
- * Hooked to the {@see 'upgrader_pre_install'} filter by {@see Theme_Upgrader::upgrade()} and
- * {@see Theme_Upgrader::bulk_upgrade()}.
- *
- * @since 2.8.0
- * @access public
- *
- * @param bool|WP_Error $return
- * @param array $theme
- * @return bool|WP_Error
- */
- public function current_before($return, $theme) {
- if ( is_wp_error($return) )
- return $return;
-
- $theme = isset($theme['theme']) ? $theme['theme'] : '';
-
- if ( $theme != get_stylesheet() ) //If not current
- return $return;
- //Change to maintenance mode now.
- if ( ! $this->bulk )
- $this->maintenance_mode(true);
-
- return $return;
- }
-
- /**
- * Turn off maintenance mode after upgrading the current theme.
- *
- * Hooked to the {@see 'upgrader_post_install'} filter by {@see Theme_Upgrader::upgrade()}
- * and {@see Theme_Upgrader::bulk_upgrade()}.
- *
- * @since 2.8.0
- * @access public
- *
- * @param bool|WP_Error $return
- * @param array $theme
- * @return bool|WP_Error
- */
- public function current_after($return, $theme) {
- if ( is_wp_error($return) )
- return $return;
-
- $theme = isset($theme['theme']) ? $theme['theme'] : '';
-
- if ( $theme != get_stylesheet() ) // If not current
- return $return;
-
- // Ensure stylesheet name hasn't changed after the upgrade:
- if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {
- wp_clean_themes_cache();
- $stylesheet = $this->result['destination_name'];
- switch_theme( $stylesheet );
- }
-
- //Time to remove maintenance mode
- if ( ! $this->bulk )
- $this->maintenance_mode(false);
- return $return;
- }
-
- /**
- * Delete the old theme during an upgrade.
- *
- * Hooked to the {@see 'upgrader_clear_destination'} filter by {@see Theme_Upgrader::upgrade()}
- * and {@see Theme_Upgrader::bulk_upgrade()}.
- *
- * @since 2.8.0
- * @access public
- *
- * @global WP_Filesystem_Base $wp_filesystem Subclass
- *
- * @param bool $removed
- * @param string $local_destination
- * @param string $remote_destination
- * @param array $theme
- * @return bool
- */
- public function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) {
- global $wp_filesystem;
-
- if ( is_wp_error( $removed ) )
- return $removed; // Pass errors through.
-
- if ( ! isset( $theme['theme'] ) )
- return $removed;
-
- $theme = $theme['theme'];
- $themes_dir = trailingslashit( $wp_filesystem->wp_themes_dir( $theme ) );
- if ( $wp_filesystem->exists( $themes_dir . $theme ) ) {
- if ( ! $wp_filesystem->delete( $themes_dir . $theme, true ) )
- return false;
- }
-
- return true;
- }
-
- /**
- * Get the WP_Theme object for a theme.
- *
- * @since 2.8.0
- * @since 3.0.0 The `$theme` argument was added.
- * @access public
- *
- * @param string $theme The directory name of the theme. This is optional, and if not supplied,
- * the directory name from the last result will be used.
- * @return WP_Theme|false The theme's info object, or false `$theme` is not supplied
- * and the last result isn't set.
- */
- public function theme_info($theme = null) {
-
- if ( empty($theme) ) {
- if ( !empty($this->result['destination_name']) )
- $theme = $this->result['destination_name'];
- else
- return false;
- }
- return wp_get_theme( $theme );
- }
-
-}
-
-/**
- * Core class used for updating/installing language packs (translations)
- * for plugins, themes, and core.
- *
- * @since 3.7.0
- *
- * @see WP_Upgrader
- */
-class Language_Pack_Upgrader extends WP_Upgrader {
-
- /**
- * Result of the language pack upgrade.
- *
- * @since 3.7.0
- * @access public
- * @var array|WP_Error $result
- * @see WP_Upgrader::$result
- */
- public $result;
-
- /**
- * Whether a bulk upgrade/install is being performed.
- *
- * @since 3.7.0
- * @access public
- * @var bool $bulk
- */
- public $bulk = true;
-
- /**
- * Asynchronously upgrades language packs after other upgrades have been made.
- *
- * Hooked to the {@see 'upgrader_process_complete'} action by default.
- *
- * @since 3.7.0
- * @access public
- * @static
- *
- * @param false|WP_Upgrader $upgrader Optional. WP_Upgrader instance or false. If `$upgrader` is
- * a Language_Pack_Upgrader instance, the method will bail to
- * avoid recursion. Otherwise unused. Default false.
- */
- public static function async_upgrade( $upgrader = false ) {
- // Avoid recursion.
- if ( $upgrader && $upgrader instanceof Language_Pack_Upgrader ) {
- return;
- }
-
- // Nothing to do?
- $language_updates = wp_get_translation_updates();
- if ( ! $language_updates ) {
- return;
- }
-
- /*
- * Avoid messing with VCS installs, at least for now.
- * Noted: this is not the ideal way to accomplish this.
- */
- $check_vcs = new WP_Automatic_Updater;
- if ( $check_vcs->is_vcs_checkout( WP_CONTENT_DIR ) ) {
- return;
- }
-
- foreach ( $language_updates as $key => $language_update ) {
- $update = ! empty( $language_update->autoupdate );
-
- /**
- * Filter whether to asynchronously update translation for core, a plugin, or a theme.
- *
- * @since 4.0.0
- *
- * @param bool $update Whether to update.
- * @param object $language_update The update offer.
- */
- $update = apply_filters( 'async_update_translation', $update, $language_update );
-
- if ( ! $update ) {
- unset( $language_updates[ $key ] );
- }
- }
-
- if ( empty( $language_updates ) ) {
- return;
- }
-
- // Re-use the automatic upgrader skin if the parent upgrader is using it.
- if ( $upgrader && $upgrader->skin instanceof Automatic_Upgrader_Skin ) {
- $skin = $upgrader->skin;
- } else {
- $skin = new Language_Pack_Upgrader_Skin( array(
- 'skip_header_footer' => true,
- ) );
- }
-
- $lp_upgrader = new Language_Pack_Upgrader( $skin );
- $lp_upgrader->bulk_upgrade( $language_updates );
- }
-
- /**
- * Initialize the upgrade strings.
- *
- * @since 3.7.0
- * @access public
- */
- public function upgrade_strings() {
- $this->strings['starting_upgrade'] = __( 'Some of your translations need updating. Sit tight for a few more seconds while we update them as well.' );
- $this->strings['up_to_date'] = __( 'The translation is up to date.' ); // We need to silently skip this case
- $this->strings['no_package'] = __( 'Update package not available.' );
- $this->strings['downloading_package'] = __( 'Downloading translation from %s…' );
- $this->strings['unpack_package'] = __( 'Unpacking the update…' );
- $this->strings['process_failed'] = __( 'Translation update failed.' );
- $this->strings['process_success'] = __( 'Translation updated successfully.' );
- }
-
- /**
- * Upgrade a language pack.
- *
- * @since 3.7.0
- * @access public
- *
- * @param string|false $update Optional. Whether an update offer is available. Default false.
- * @param array $args Optional. Other optional arguments, see
- * {@see Language_Pack_Upgrader::bulk_upgrade()}. Default empty array.
- * @return array|bool|WP_Error The result of the upgrade, or a {@see wP_Error} object instead.
- */
- public function upgrade( $update = false, $args = array() ) {
- if ( $update ) {
- $update = array( $update );
- }
-
- $results = $this->bulk_upgrade( $update, $args );
-
- if ( ! is_array( $results ) ) {
- return $results;
- }
-
- return $results[0];
- }
-
- /**
- * Bulk upgrade language packs.
- *
- * @since 3.7.0
- * @access public
- *
- * @global WP_Filesystem_Base $wp_filesystem Subclass
- *
- * @param array $language_updates Optional. Language pack updates. Default empty array.
- * @param array $args {
- * Optional. Other arguments for upgrading multiple language packs. Default empty array
- *
- * @type bool $clear_update_cache Whether to clear the update cache when done.
- * Default true.
- * }
- * @return array|bool|WP_Error Will return an array of results, or true if there are no updates,
- * false or WP_Error for initial errors.
- */
- public function bulk_upgrade( $language_updates = array(), $args = array() ) {
- global $wp_filesystem;
-
- $defaults = array(
- 'clear_update_cache' => true,
- );
- $parsed_args = wp_parse_args( $args, $defaults );
-
- $this->init();
- $this->upgrade_strings();
-
- if ( ! $language_updates )
- $language_updates = wp_get_translation_updates();
-
- if ( empty( $language_updates ) ) {
- $this->skin->header();
- $this->skin->before();
- $this->skin->set_result( true );
- $this->skin->feedback( 'up_to_date' );
- $this->skin->after();
- $this->skin->bulk_footer();
- $this->skin->footer();
- return true;
- }
-
- if ( 'upgrader_process_complete' == current_filter() )
- $this->skin->feedback( 'starting_upgrade' );
-
- // Remove any existing upgrade filters from the plugin/theme upgraders #WP29425 & #WP29230
- remove_all_filters( 'upgrader_pre_install' );
- remove_all_filters( 'upgrader_clear_destination' );
- remove_all_filters( 'upgrader_post_install' );
- remove_all_filters( 'upgrader_source_selection' );
-
- add_filter( 'upgrader_source_selection', array( $this, 'check_package' ), 10, 2 );
-
- $this->skin->header();
-
- // Connect to the Filesystem first.
- $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) );
- if ( ! $res ) {
- $this->skin->footer();
- return false;
- }
-
- $results = array();
-
- $this->update_count = count( $language_updates );
- $this->update_current = 0;
-
- /*
- * The filesystem's mkdir() is not recursive. Make sure WP_LANG_DIR exists,
- * as we then may need to create a /plugins or /themes directory inside of it.
- */
- $remote_destination = $wp_filesystem->find_folder( WP_LANG_DIR );
- if ( ! $wp_filesystem->exists( $remote_destination ) )
- if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) )
- return new WP_Error( 'mkdir_failed_lang_dir', $this->strings['mkdir_failed'], $remote_destination );
-
- foreach ( $language_updates as $language_update ) {
-
- $this->skin->language_update = $language_update;
-
- $destination = WP_LANG_DIR;
- if ( 'plugin' == $language_update->type )
- $destination .= '/plugins';
- elseif ( 'theme' == $language_update->type )
- $destination .= '/themes';
-
- $this->update_current++;
-
- $options = array(
- 'package' => $language_update->package,
- 'destination' => $destination,
- 'clear_destination' => false,
- 'abort_if_destination_exists' => false, // We expect the destination to exist.
- 'clear_working' => true,
- 'is_multi' => true,
- 'hook_extra' => array(
- 'language_update_type' => $language_update->type,
- 'language_update' => $language_update,
- )
- );
-
- $result = $this->run( $options );
-
- $results[] = $this->result;
-
- // Prevent credentials auth screen from displaying multiple times.
- if ( false === $result )
- break;
- }
-
- $this->skin->bulk_footer();
-
- $this->skin->footer();
-
- // Clean up our hooks, in case something else does an upgrade on this connection.
- remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
-
- if ( $parsed_args['clear_update_cache'] ) {
- wp_clean_update_cache();
- }
-
- return $results;
- }
-
- /**
- * Check the package source to make sure there are .mo and .po files.
- *
- * Hooked to the {@see 'upgrader_source_selection'} filter by
- * {@see Language_Pack_Upgrader::bulk_upgrade()}.
- *
- * @since 3.7.0
- * @access public
- *
- * @global WP_Filesystem_Base $wp_filesystem Subclass
- *
- * @param string|WP_Error $source
- * @param string $remote_source
- */
- public function check_package( $source, $remote_source ) {
- global $wp_filesystem;
-
- if ( is_wp_error( $source ) )
- return $source;
-
- // Check that the folder contains a valid language.
- $files = $wp_filesystem->dirlist( $remote_source );
-
- // Check to see if a .po and .mo exist in the folder.
- $po = $mo = false;
- foreach ( (array) $files as $file => $filedata ) {
- if ( '.po' == substr( $file, -3 ) )
- $po = true;
- elseif ( '.mo' == substr( $file, -3 ) )
- $mo = true;
- }
-
- if ( ! $mo || ! $po ) {
- return new WP_Error( 'incompatible_archive_pomo', $this->strings['incompatible_archive'],
- /* translators: 1: .po 2: .mo */
- sprintf( __( 'The language pack is missing either the %1$s or %2$s files.' ),
- '.po
',
- '.mo
'
- )
- );
- }
-
- return $source;
- }
-
- /**
- * Get the name of an item being updated.
- *
- * @since 3.7.0
- * @access public
- *
- * @param object $update The data for an update.
- * @return string The name of the item being updated.
- */
- public function get_name_for_update( $update ) {
- switch ( $update->type ) {
- case 'core':
- return 'WordPress'; // Not translated
-
- case 'theme':
- $theme = wp_get_theme( $update->slug );
- if ( $theme->exists() )
- return $theme->Get( 'Name' );
- break;
- case 'plugin':
- $plugin_data = get_plugins( '/' . $update->slug );
- $plugin_data = reset( $plugin_data );
- if ( $plugin_data )
- return $plugin_data['Name'];
- break;
- }
- return '';
- }
-
-}
-
-/**
- * Core class used for updating core.
- *
- * It allows for WordPress to upgrade itself in combination with
- * the wp-admin/includes/update-core.php file.
- *
- * @since 2.8.0
- *
- * @see WP_Upgrader
- */
-class Core_Upgrader extends WP_Upgrader {
-
- /**
- * Initialize the upgrade strings.
- *
- * @since 2.8.0
- * @access public
- */
- public function upgrade_strings() {
- $this->strings['up_to_date'] = __('WordPress is at the latest version.');
- $this->strings['locked'] = __('Another update is currently in progress.');
- $this->strings['no_package'] = __('Update package not available.');
- $this->strings['downloading_package'] = __('Downloading update from %s…');
- $this->strings['unpack_package'] = __('Unpacking the update…');
- $this->strings['copy_failed'] = __('Could not copy files.');
- $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' );
- $this->strings['start_rollback'] = __( 'Attempting to roll back to previous version.' );
- $this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has rolled back to your previous version.' );
- }
-
- /**
- * Upgrade WordPress core.
- *
- * @since 2.8.0
- * @access public
- *
- * @global WP_Filesystem_Base $wp_filesystem Subclass
- * @global callable $_wp_filesystem_direct_method
- *
- * @param object $current Response object for whether WordPress is current.
- * @param array $args {
- * Optional. Arguments for upgrading WordPress core. Default empty array.
- *
- * @type bool $pre_check_md5 Whether to check the file checksums before
- * attempting the upgrade. Default true.
- * @type bool $attempt_rollback Whether to attempt to rollback the chances if
- * there is a problem. Default false.
- * @type bool $do_rollback Whether to perform this "upgrade" as a rollback.
- * Default false.
- * }
- * @return null|false|WP_Error False or WP_Error on failure, null on success.
- */
- public function upgrade( $current, $args = array() ) {
- global $wp_filesystem;
-
- include( ABSPATH . WPINC . '/version.php' ); // $wp_version;
-
- $start_time = time();
-
- $defaults = array(
- 'pre_check_md5' => true,
- 'attempt_rollback' => false,
- 'do_rollback' => false,
- 'allow_relaxed_file_ownership' => false,
- );
- $parsed_args = wp_parse_args( $args, $defaults );
-
- $this->init();
- $this->upgrade_strings();
-
- // Is an update available?
- if ( !isset( $current->response ) || $current->response == 'latest' )
- return new WP_Error('up_to_date', $this->strings['up_to_date']);
-
- $res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] );
- if ( ! $res || is_wp_error( $res ) ) {
- return $res;
- }
-
- $wp_dir = trailingslashit($wp_filesystem->abspath());
-
- $partial = true;
- if ( $parsed_args['do_rollback'] )
- $partial = false;
- elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() )
- $partial = false;
-
- /*
- * If partial update is returned from the API, use that, unless we're doing
- * a reinstall. If we cross the new_bundled version number, then use
- * the new_bundled zip. Don't though if the constant is set to skip bundled items.
- * If the API returns a no_content zip, go with it. Finally, default to the full zip.
- */
- if ( $parsed_args['do_rollback'] && $current->packages->rollback )
- $to_download = 'rollback';
- elseif ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && $partial )
- $to_download = 'partial';
- elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )
- && ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) )
- $to_download = 'new_bundled';
- elseif ( $current->packages->no_content )
- $to_download = 'no_content';
- else
- $to_download = 'full';
-
- // Lock to prevent multiple Core Updates occuring
- $lock = WP_Upgrader::create_lock( 'core_updater', 15 * MINUTE_IN_SECONDS );
- if ( ! $lock ) {
- return new WP_Error( 'locked', $this->strings['locked'] );
- }
-
- $download = $this->download_package( $current->packages->$to_download );
- if ( is_wp_error( $download ) ) {
- WP_Upgrader::release_lock( 'core_updater' );
- return $download;
- }
-
- $working_dir = $this->unpack_package( $download );
- if ( is_wp_error( $working_dir ) ) {
- WP_Upgrader::release_lock( 'core_updater' );
- return $working_dir;
- }
-
- // Copy update-core.php from the new version into place.
- if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {
- $wp_filesystem->delete($working_dir, true);
- WP_Upgrader::release_lock( 'core_updater' );
- return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' );
- }
- $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
-
- require_once( ABSPATH . 'wp-admin/includes/update-core.php' );
-
- if ( ! function_exists( 'update_core' ) ) {
- WP_Upgrader::release_lock( 'core_updater' );
- return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] );
- }
-
- $result = update_core( $working_dir, $wp_dir );
-
- // In the event of an issue, we may be able to roll back.
- if ( $parsed_args['attempt_rollback'] && $current->packages->rollback && ! $parsed_args['do_rollback'] ) {
- $try_rollback = false;
- if ( is_wp_error( $result ) ) {
- $error_code = $result->get_error_code();
- /*
- * Not all errors are equal. These codes are critical: copy_failed__copy_dir,
- * mkdir_failed__copy_dir, copy_failed__copy_dir_retry, and disk_full.
- * do_rollback allows for update_core() to trigger a rollback if needed.
- */
- if ( false !== strpos( $error_code, 'do_rollback' ) )
- $try_rollback = true;
- elseif ( false !== strpos( $error_code, '__copy_dir' ) )
- $try_rollback = true;
- elseif ( 'disk_full' === $error_code )
- $try_rollback = true;
- }
-
- if ( $try_rollback ) {
- /** This filter is documented in wp-admin/includes/update-core.php */
- apply_filters( 'update_feedback', $result );
-
- /** This filter is documented in wp-admin/includes/update-core.php */
- apply_filters( 'update_feedback', $this->strings['start_rollback'] );
-
- $rollback_result = $this->upgrade( $current, array_merge( $parsed_args, array( 'do_rollback' => true ) ) );
-
- $original_result = $result;
- $result = new WP_Error( 'rollback_was_required', $this->strings['rollback_was_required'], (object) array( 'update' => $original_result, 'rollback' => $rollback_result ) );
- }
- }
-
- /** This action is documented in wp-admin/includes/class-wp-upgrader.php */
- do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'core' ) );
-
- // Clear the current updates
- delete_site_transient( 'update_core' );
-
- if ( ! $parsed_args['do_rollback'] ) {
- $stats = array(
- 'update_type' => $current->response,
- 'success' => true,
- 'fs_method' => $wp_filesystem->method,
- 'fs_method_forced' => defined( 'FS_METHOD' ) || has_filter( 'filesystem_method' ),
- 'fs_method_direct' => !empty( $GLOBALS['_wp_filesystem_direct_method'] ) ? $GLOBALS['_wp_filesystem_direct_method'] : '',
- 'time_taken' => time() - $start_time,
- 'reported' => $wp_version,
- 'attempted' => $current->version,
- );
-
- if ( is_wp_error( $result ) ) {
- $stats['success'] = false;
- // Did a rollback occur?
- if ( ! empty( $try_rollback ) ) {
- $stats['error_code'] = $original_result->get_error_code();
- $stats['error_data'] = $original_result->get_error_data();
- // Was the rollback successful? If not, collect its error too.
- $stats['rollback'] = ! is_wp_error( $rollback_result );
- if ( is_wp_error( $rollback_result ) ) {
- $stats['rollback_code'] = $rollback_result->get_error_code();
- $stats['rollback_data'] = $rollback_result->get_error_data();
- }
- } else {
- $stats['error_code'] = $result->get_error_code();
- $stats['error_data'] = $result->get_error_data();
- }
- }
-
- wp_version_check( $stats );
- }
-
- WP_Upgrader::release_lock( 'core_updater' );
-
- return $result;
- }
-
- /**
- * Determines if this WordPress Core version should update to an offered version or not.
- *
- * @since 3.7.0
- * @access public
- *
- * @static
- *
- * @param string $offered_ver The offered version, of the format x.y.z.
- * @return bool True if we should update to the offered version, otherwise false.
- */
- public static function should_update_to_version( $offered_ver ) {
- include( ABSPATH . WPINC . '/version.php' ); // $wp_version; // x.y.z
-
- $current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version ), 0, 2 ) ); // x.y
- $new_branch = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y
- $current_is_development_version = (bool) strpos( $wp_version, '-' );
-
- // Defaults:
- $upgrade_dev = true;
- $upgrade_minor = true;
- $upgrade_major = false;
-
- // WP_AUTO_UPDATE_CORE = true (all), 'minor', false.
- if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) {
- if ( false === WP_AUTO_UPDATE_CORE ) {
- // Defaults to turned off, unless a filter allows it
- $upgrade_dev = $upgrade_minor = $upgrade_major = false;
- } elseif ( true === WP_AUTO_UPDATE_CORE ) {
- // ALL updates for core
- $upgrade_dev = $upgrade_minor = $upgrade_major = true;
- } elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) {
- // Only minor updates for core
- $upgrade_dev = $upgrade_major = false;
- $upgrade_minor = true;
- }
- }
-
- // 1: If we're already on that version, not much point in updating?
- if ( $offered_ver == $wp_version )
- return false;
-
- // 2: If we're running a newer version, that's a nope
- if ( version_compare( $wp_version, $offered_ver, '>' ) )
- return false;
-
- $failure_data = get_site_option( 'auto_core_update_failed' );
- if ( $failure_data ) {
- // If this was a critical update failure, cannot update.
- if ( ! empty( $failure_data['critical'] ) )
- return false;
-
- // Don't claim we can update on update-core.php if we have a non-critical failure logged.
- if ( $wp_version == $failure_data['current'] && false !== strpos( $offered_ver, '.1.next.minor' ) )
- return false;
-
- // Cannot update if we're retrying the same A to B update that caused a non-critical failure.
- // Some non-critical failures do allow retries, like download_failed.
- // 3.7.1 => 3.7.2 resulted in files_not_writable, if we are still on 3.7.1 and still trying to update to 3.7.2.
- if ( empty( $failure_data['retry'] ) && $wp_version == $failure_data['current'] && $offered_ver == $failure_data['attempted'] )
- return false;
- }
-
- // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2
- if ( $current_is_development_version ) {
-
- /**
- * Filter whether to enable automatic core updates for development versions.
- *
- * @since 3.7.0
- *
- * @param bool $upgrade_dev Whether to enable automatic updates for
- * development versions.
- */
- if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) )
- return false;
- // Else fall through to minor + major branches below.
- }
-
- // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4)
- if ( $current_branch == $new_branch ) {
-
- /**
- * Filter whether to enable minor automatic core updates.
- *
- * @since 3.7.0
- *
- * @param bool $upgrade_minor Whether to enable minor automatic core updates.
- */
- return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor );
- }
-
- // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1)
- if ( version_compare( $new_branch, $current_branch, '>' ) ) {
-
- /**
- * Filter whether to enable major automatic core updates.
- *
- * @since 3.7.0
- *
- * @param bool $upgrade_major Whether to enable major automatic core updates.
- */
- return apply_filters( 'allow_major_auto_core_updates', $upgrade_major );
- }
-
- // If we're not sure, we don't want it
- return false;
- }
-
- /**
- * Compare the disk file checksums against the expected checksums.
- *
- * @since 3.7.0
- * @access public
- *
- * @global string $wp_version
- * @global string $wp_local_package
- *
- * @return bool True if the checksums match, otherwise false.
- */
- public function check_files() {
- global $wp_version, $wp_local_package;
-
- $checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' );
-
- if ( ! is_array( $checksums ) )
- return false;
-
- foreach ( $checksums as $file => $checksum ) {
- // Skip files which get updated
- if ( 'wp-content' == substr( $file, 0, 10 ) )
- continue;
- if ( ! file_exists( ABSPATH . $file ) || md5_file( ABSPATH . $file ) !== $checksum )
- return false;
- }
-
- return true;
- }
-}
-
-/**
- * Core class used for handling file uploads.
- *
- * This class handles the upload process and passes it as if it's a local file
- * to the Upgrade/Installer functions.
- *
- * @since 2.8.0
- */
-class File_Upload_Upgrader {
-
- /**
- * The full path to the file package.
- *
- * @since 2.8.0
- * @access public
- * @var string $package
- */
- public $package;
-
- /**
- * The name of the file.
- *
- * @since 2.8.0
- * @access public
- * @var string $filename
- */
- public $filename;
-
- /**
- * The ID of the attachment post for this file.
- *
- * @since 3.3.0
- * @access public
- * @var int $id
- */
- public $id = 0;
-
- /**
- * Construct the upgrader for a form.
- *
- * @since 2.8.0
- * @access public
- *
- * @param string $form The name of the form the file was uploaded from.
- * @param string $urlholder The name of the `GET` parameter that holds the filename.
- */
- public function __construct( $form, $urlholder ) {
-
- if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) )
- wp_die(__('Please select a file'));
-
- //Handle a newly uploaded file, Else assume it's already been uploaded
- if ( ! empty($_FILES) ) {
- $overrides = array( 'test_form' => false, 'test_type' => false );
- $file = wp_handle_upload( $_FILES[$form], $overrides );
-
- if ( isset( $file['error'] ) )
- wp_die( $file['error'] );
-
- $this->filename = $_FILES[$form]['name'];
- $this->package = $file['file'];
-
- // Construct the object array
- $object = array(
- 'post_title' => $this->filename,
- 'post_content' => $file['url'],
- 'post_mime_type' => $file['type'],
- 'guid' => $file['url'],
- 'context' => 'upgrader',
- 'post_status' => 'private'
- );
-
- // Save the data.
- $this->id = wp_insert_attachment( $object, $file['file'] );
-
- // Schedule a cleanup for 2 hours from now in case of failed install.
- wp_schedule_single_event( time() + 2 * HOUR_IN_SECONDS, 'upgrader_scheduled_cleanup', array( $this->id ) );
-
- } elseif ( is_numeric( $_GET[$urlholder] ) ) {
- // Numeric Package = previously uploaded file, see above.
- $this->id = (int) $_GET[$urlholder];
- $attachment = get_post( $this->id );
- if ( empty($attachment) )
- wp_die(__('Please select a file'));
-
- $this->filename = $attachment->post_title;
- $this->package = get_attached_file( $attachment->ID );
- } else {
- // Else, It's set to something, Back compat for plugins using the old (pre-3.3) File_Uploader handler.
- if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )
- wp_die( $uploads['error'] );
-
- $this->filename = $_GET[$urlholder];
- $this->package = $uploads['basedir'] . '/' . $this->filename;
- }
- }
-
- /**
- * Delete the attachment/uploaded file.
- *
- * @since 3.2.2
- * @access public
- *
- * @return bool Whether the cleanup was successful.
- */
- public function cleanup() {
- if ( $this->id )
- wp_delete_attachment( $this->id );
-
- elseif ( file_exists( $this->package ) )
- return @unlink( $this->package );
-
- return true;
- }
-}
-
-/**
- * Core class used for handling automatic background updates.
- *
- * @since 3.7.0
- */
-class WP_Automatic_Updater {
-
- /**
- * Tracks update results during processing.
- *
- * @var array
- * @access protected
- */
- protected $update_results = array();
-
- /**
- * Whether the entire automatic updater is disabled.
- *
- * @since 3.7.0
- * @access public
- */
- public function is_disabled() {
- // Background updates are disabled if you don't want file changes.
- if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
- return true;
-
- if ( wp_installing() )
- return true;
-
- // More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters.
- $disabled = defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED;
-
- /**
- * Filter whether to entirely disable background updates.
- *
- * There are more fine-grained filters and controls for selective disabling.
- * This filter parallels the AUTOMATIC_UPDATER_DISABLED constant in name.
- *
- * This also disables update notification emails. That may change in the future.
- *
- * @since 3.7.0
- *
- * @param bool $disabled Whether the updater should be disabled.
- */
- return apply_filters( 'automatic_updater_disabled', $disabled );
- }
-
- /**
- * Check for version control checkouts.
- *
- * Checks for Subversion, Git, Mercurial, and Bazaar. It recursively looks up the
- * filesystem to the top of the drive, erring on the side of detecting a VCS
- * checkout somewhere.
- *
- * ABSPATH is always checked in addition to whatever $context is (which may be the
- * wp-content directory, for example). The underlying assumption is that if you are
- * using version control *anywhere*, then you should be making decisions for
- * how things get updated.
- *
- * @since 3.7.0
- * @access public
- *
- * @param string $context The filesystem path to check, in addition to ABSPATH.
- */
- public function is_vcs_checkout( $context ) {
- $context_dirs = array( untrailingslashit( $context ) );
- if ( $context !== ABSPATH )
- $context_dirs[] = untrailingslashit( ABSPATH );
-
- $vcs_dirs = array( '.svn', '.git', '.hg', '.bzr' );
- $check_dirs = array();
-
- foreach ( $context_dirs as $context_dir ) {
- // Walk up from $context_dir to the root.
- do {
- $check_dirs[] = $context_dir;
-
- // Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
- if ( $context_dir == dirname( $context_dir ) )
- break;
-
- // Continue one level at a time.
- } while ( $context_dir = dirname( $context_dir ) );
- }
-
- $check_dirs = array_unique( $check_dirs );
-
- // Search all directories we've found for evidence of version control.
- foreach ( $vcs_dirs as $vcs_dir ) {
- foreach ( $check_dirs as $check_dir ) {
- if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) )
- break 2;
- }
- }
-
- /**
- * Filter whether the automatic updater should consider a filesystem
- * location to be potentially managed by a version control system.
- *
- * @since 3.7.0
- *
- * @param bool $checkout Whether a VCS checkout was discovered at $context
- * or ABSPATH, or anywhere higher.
- * @param string $context The filesystem context (a path) against which
- * filesystem status should be checked.
- */
- return apply_filters( 'automatic_updates_is_vcs_checkout', $checkout, $context );
- }
-
- /**
- * Tests to see if we can and should update a specific item.
- *
- * @since 3.7.0
- * @access public
- *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
- * @param string $type The type of update being checked: 'core', 'theme',
- * 'plugin', 'translation'.
- * @param object $item The update offer.
- * @param string $context The filesystem context (a path) against which filesystem
- * access and status should be checked.
- */
- public function should_update( $type, $item, $context ) {
- // Used to see if WP_Filesystem is set up to allow unattended updates.
- $skin = new Automatic_Upgrader_Skin;
-
- if ( $this->is_disabled() )
- return false;
-
- // Only relax the filesystem checks when the update doesn't include new files
- $allow_relaxed_file_ownership = false;
- if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
- $allow_relaxed_file_ownership = true;
- }
-
- // If we can't do an auto core update, we may still be able to email the user.
- if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) {
- if ( 'core' == $type )
- $this->send_core_update_notification_email( $item );
- return false;
- }
-
- // Next up, is this an item we can update?
- if ( 'core' == $type )
- $update = Core_Upgrader::should_update_to_version( $item->current );
- else
- $update = ! empty( $item->autoupdate );
-
- /**
- * Filter whether to automatically update core, a plugin, a theme, or a language.
- *
- * The dynamic portion of the hook name, `$type`, refers to the type of update
- * being checked. Can be 'core', 'theme', 'plugin', or 'translation'.
- *
- * Generally speaking, plugins, themes, and major core versions are not updated
- * by default, while translations and minor and development versions for core
- * are updated by default.
- *
- * See the {@see 'allow_dev_auto_core_updates', {@see 'allow_minor_auto_core_updates'},
- * and {@see 'allow_major_auto_core_updates'} filters for a more straightforward way to
- * adjust core updates.
- *
- * @since 3.7.0
- *
- * @param bool $update Whether to update.
- * @param object $item The update offer.
- */
- $update = apply_filters( 'auto_update_' . $type, $update, $item );
-
- if ( ! $update ) {
- if ( 'core' == $type )
- $this->send_core_update_notification_email( $item );
- return false;
- }
-
- // If it's a core update, are we actually compatible with its requirements?
- if ( 'core' == $type ) {
- global $wpdb;
-
- $php_compat = version_compare( phpversion(), $item->php_version, '>=' );
- if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) )
- $mysql_compat = true;
- else
- $mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' );
-
- if ( ! $php_compat || ! $mysql_compat )
- return false;
- }
-
- return true;
- }
-
- /**
- * Notifies an administrator of a core update.
- *
- * @since 3.7.0
- * @access protected
- *
- * @param object $item The update offer.
- */
- protected function send_core_update_notification_email( $item ) {
- $notified = get_site_option( 'auto_core_update_notified' );
-
- // Don't notify if we've already notified the same email address of the same version.
- if ( $notified && $notified['email'] == get_site_option( 'admin_email' ) && $notified['version'] == $item->current )
- return false;
-
- // See if we need to notify users of a core update.
- $notify = ! empty( $item->notify_email );
-
- /**
- * Filter whether to notify the site administrator of a new core update.
- *
- * By default, administrators are notified when the update offer received
- * from WordPress.org sets a particular flag. This allows some discretion
- * in if and when to notify.
- *
- * This filter is only evaluated once per release. If the same email address
- * was already notified of the same new version, WordPress won't repeatedly
- * email the administrator.
- *
- * This filter is also used on about.php to check if a plugin has disabled
- * these notifications.
- *
- * @since 3.7.0
- *
- * @param bool $notify Whether the site administrator is notified.
- * @param object $item The update offer.
- */
- if ( ! apply_filters( 'send_core_update_notification_email', $notify, $item ) )
- return false;
-
- $this->send_email( 'manual', $item );
- return true;
- }
-
- /**
- * Update an item, if appropriate.
- *
- * @since 3.7.0
- * @access public
- *
- * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'.
- * @param object $item The update offer.
- *
- * @return null|WP_Error
- */
- public function update( $type, $item ) {
- $skin = new Automatic_Upgrader_Skin;
-
- switch ( $type ) {
- case 'core':
- // The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter.
- add_filter( 'update_feedback', array( $skin, 'feedback' ) );
- $upgrader = new Core_Upgrader( $skin );
- $context = ABSPATH;
- break;
- case 'plugin':
- $upgrader = new Plugin_Upgrader( $skin );
- $context = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR
- break;
- case 'theme':
- $upgrader = new Theme_Upgrader( $skin );
- $context = get_theme_root( $item->theme );
- break;
- case 'translation':
- $upgrader = new Language_Pack_Upgrader( $skin );
- $context = WP_CONTENT_DIR; // WP_LANG_DIR;
- break;
- }
-
- // Determine whether we can and should perform this update.
- if ( ! $this->should_update( $type, $item, $context ) )
- return false;
-
- /**
- * Fires immediately prior to an auto-update.
- *
- * @since 4.4.0
- *
- * @param string $type The type of update being checked: 'core', 'theme', 'plugin', or 'translation'.
- * @param object $item The update offer.
- * @param string $context The filesystem context (a path) against which filesystem access and status
- * should be checked.
- */
- do_action( 'pre_auto_update', $type, $item, $context );
-
- $upgrader_item = $item;
- switch ( $type ) {
- case 'core':
- $skin->feedback( __( 'Updating to WordPress %s' ), $item->version );
- $item_name = sprintf( __( 'WordPress %s' ), $item->version );
- break;
- case 'theme':
- $upgrader_item = $item->theme;
- $theme = wp_get_theme( $upgrader_item );
- $item_name = $theme->Get( 'Name' );
- $skin->feedback( __( 'Updating theme: %s' ), $item_name );
- break;
- case 'plugin':
- $upgrader_item = $item->plugin;
- $plugin_data = get_plugin_data( $context . '/' . $upgrader_item );
- $item_name = $plugin_data['Name'];
- $skin->feedback( __( 'Updating plugin: %s' ), $item_name );
- break;
- case 'translation':
- $language_item_name = $upgrader->get_name_for_update( $item );
- $item_name = sprintf( __( 'Translations for %s' ), $language_item_name );
- $skin->feedback( sprintf( __( 'Updating translations for %1$s (%2$s)…' ), $language_item_name, $item->language ) );
- break;
- }
-
- $allow_relaxed_file_ownership = false;
- if ( 'core' == $type && isset( $item->new_files ) && ! $item->new_files ) {
- $allow_relaxed_file_ownership = true;
- }
-
- // Boom, This sites about to get a whole new splash of paint!
- $upgrade_result = $upgrader->upgrade( $upgrader_item, array(
- 'clear_update_cache' => false,
- // Always use partial builds if possible for core updates.
- 'pre_check_md5' => false,
- // Only available for core updates.
- 'attempt_rollback' => true,
- // Allow relaxed file ownership in some scenarios
- 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
- ) );
-
- // If the filesystem is unavailable, false is returned.
- if ( false === $upgrade_result ) {
- $upgrade_result = new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
- }
-
- if ( 'core' == $type ) {
- if ( is_wp_error( $upgrade_result ) && ( 'up_to_date' == $upgrade_result->get_error_code() || 'locked' == $upgrade_result->get_error_code() ) ) {
- // These aren't actual errors, treat it as a skipped-update instead to avoid triggering the post-core update failure routines.
- return false;
- }
-
- // Core doesn't output this, so let's append it so we don't get confused.
- if ( is_wp_error( $upgrade_result ) ) {
- $skin->error( __( 'Installation Failed' ), $upgrade_result );
- } else {
- $skin->feedback( __( 'WordPress updated successfully' ) );
- }
- }
-
- $this->update_results[ $type ][] = (object) array(
- 'item' => $item,
- 'result' => $upgrade_result,
- 'name' => $item_name,
- 'messages' => $skin->get_upgrade_messages()
- );
-
- return $upgrade_result;
- }
-
- /**
- * Kicks off the background update process, looping through all pending updates.
- *
- * @since 3.7.0
- * @access public
- *
- * @global wpdb $wpdb
- * @global string $wp_version
- */
- public function run() {
- global $wpdb, $wp_version;
-
- if ( $this->is_disabled() )
- return;
-
- if ( ! is_main_network() || ! is_main_site() )
- return;
-
- if ( ! WP_Upgrader::create_lock( 'auto_updater' ) )
- return;
-
- // Don't automatically run these thins, as we'll handle it ourselves
- remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
- remove_action( 'upgrader_process_complete', 'wp_version_check' );
- remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
- remove_action( 'upgrader_process_complete', 'wp_update_themes' );
-
- // Next, Plugins
- wp_update_plugins(); // Check for Plugin updates
- $plugin_updates = get_site_transient( 'update_plugins' );
- if ( $plugin_updates && !empty( $plugin_updates->response ) ) {
- foreach ( $plugin_updates->response as $plugin ) {
- $this->update( 'plugin', $plugin );
- }
- // Force refresh of plugin update information
- wp_clean_plugins_cache();
- }
-
- // Next, those themes we all love
- wp_update_themes(); // Check for Theme updates
- $theme_updates = get_site_transient( 'update_themes' );
- if ( $theme_updates && !empty( $theme_updates->response ) ) {
- foreach ( $theme_updates->response as $theme ) {
- $this->update( 'theme', (object) $theme );
- }
- // Force refresh of theme update information
- wp_clean_themes_cache();
- }
-
- // Next, Process any core update
- wp_version_check(); // Check for Core updates
- $core_update = find_core_auto_update();
-
- if ( $core_update )
- $this->update( 'core', $core_update );
-
- // Clean up, and check for any pending translations
- // (Core_Upgrader checks for core updates)
- $theme_stats = array();
- if ( isset( $this->update_results['theme'] ) ) {
- foreach ( $this->update_results['theme'] as $upgrade ) {
- $theme_stats[ $upgrade->item->theme ] = ( true === $upgrade->result );
- }
- }
- wp_update_themes( $theme_stats ); // Check for Theme updates
-
- $plugin_stats = array();
- if ( isset( $this->update_results['plugin'] ) ) {
- foreach ( $this->update_results['plugin'] as $upgrade ) {
- $plugin_stats[ $upgrade->item->plugin ] = ( true === $upgrade->result );
- }
- }
- wp_update_plugins( $plugin_stats ); // Check for Plugin updates
-
- // Finally, Process any new translations
- $language_updates = wp_get_translation_updates();
- if ( $language_updates ) {
- foreach ( $language_updates as $update ) {
- $this->update( 'translation', $update );
- }
-
- // Clear existing caches
- wp_clean_update_cache();
-
- wp_version_check(); // check for Core updates
- wp_update_themes(); // Check for Theme updates
- wp_update_plugins(); // Check for Plugin updates
- }
-
- // Send debugging email to all development installs.
- if ( ! empty( $this->update_results ) ) {
- $development_version = false !== strpos( $wp_version, '-' );
-
- /**
- * Filter whether to send a debugging email for each automatic background update.
- *
- * @since 3.7.0
- *
- * @param bool $development_version By default, emails are sent if the
- * install is a development version.
- * Return false to avoid the email.
- */
- if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) )
- $this->send_debug_email();
-
- if ( ! empty( $this->update_results['core'] ) )
- $this->after_core_update( $this->update_results['core'][0] );
-
- /**
- * Fires after all automatic updates have run.
- *
- * @since 3.8.0
- *
- * @param array $update_results The results of all attempted updates.
- */
- do_action( 'automatic_updates_complete', $this->update_results );
- }
-
- WP_Upgrader::release_lock( 'auto_updater' );
- }
-
- /**
- * If we tried to perform a core update, check if we should send an email,
- * and if we need to avoid processing future updates.
- *
- * @since Unknown
- * @access protected
- *
- * @global string $wp_version
- *
- * @param object $update_result The result of the core update. Includes the update offer and result.
- */
- protected function after_core_update( $update_result ) {
- global $wp_version;
-
- $core_update = $update_result->item;
- $result = $update_result->result;
-
- if ( ! is_wp_error( $result ) ) {
- $this->send_email( 'success', $core_update );
- return;
- }
-
- $error_code = $result->get_error_code();
-
- // Any of these WP_Error codes are critical failures, as in they occurred after we started to copy core files.
- // We should not try to perform a background update again until there is a successful one-click update performed by the user.
- $critical = false;
- if ( $error_code === 'disk_full' || false !== strpos( $error_code, '__copy_dir' ) ) {
- $critical = true;
- } elseif ( $error_code === 'rollback_was_required' && is_wp_error( $result->get_error_data()->rollback ) ) {
- // A rollback is only critical if it failed too.
- $critical = true;
- $rollback_result = $result->get_error_data()->rollback;
- } elseif ( false !== strpos( $error_code, 'do_rollback' ) ) {
- $critical = true;
- }
-
- if ( $critical ) {
- $critical_data = array(
- 'attempted' => $core_update->current,
- 'current' => $wp_version,
- 'error_code' => $error_code,
- 'error_data' => $result->get_error_data(),
- 'timestamp' => time(),
- 'critical' => true,
- );
- if ( isset( $rollback_result ) ) {
- $critical_data['rollback_code'] = $rollback_result->get_error_code();
- $critical_data['rollback_data'] = $rollback_result->get_error_data();
- }
- update_site_option( 'auto_core_update_failed', $critical_data );
- $this->send_email( 'critical', $core_update, $result );
- return;
- }
-
- /*
- * Any other WP_Error code (like download_failed or files_not_writable) occurs before
- * we tried to copy over core files. Thus, the failures are early and graceful.
- *
- * We should avoid trying to perform a background update again for the same version.
- * But we can try again if another version is released.
- *
- * For certain 'transient' failures, like download_failed, we should allow retries.
- * In fact, let's schedule a special update for an hour from now. (It's possible
- * the issue could actually be on WordPress.org's side.) If that one fails, then email.
- */
- $send = true;
- $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro', 'locked' );
- if ( in_array( $error_code, $transient_failures ) && ! get_site_option( 'auto_core_update_failed' ) ) {
- wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' );
- $send = false;
- }
-
- $n = get_site_option( 'auto_core_update_notified' );
- // Don't notify if we've already notified the same email address of the same version of the same notification type.
- if ( $n && 'fail' == $n['type'] && $n['email'] == get_site_option( 'admin_email' ) && $n['version'] == $core_update->current )
- $send = false;
-
- update_site_option( 'auto_core_update_failed', array(
- 'attempted' => $core_update->current,
- 'current' => $wp_version,
- 'error_code' => $error_code,
- 'error_data' => $result->get_error_data(),
- 'timestamp' => time(),
- 'retry' => in_array( $error_code, $transient_failures ),
- ) );
-
- if ( $send )
- $this->send_email( 'fail', $core_update, $result );
- }
-
- /**
- * Sends an email upon the completion or failure of a background core update.
- *
- * @since 3.7.0
- * @access protected
- *
- * @global string $wp_version
- *
- * @param string $type The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'.
- * @param object $core_update The update offer that was attempted.
- * @param mixed $result Optional. The result for the core update. Can be WP_Error.
- */
- protected function send_email( $type, $core_update, $result = null ) {
- update_site_option( 'auto_core_update_notified', array(
- 'type' => $type,
- 'email' => get_site_option( 'admin_email' ),
- 'version' => $core_update->current,
- 'timestamp' => time(),
- ) );
-
- $next_user_core_update = get_preferred_from_update_core();
- // If the update transient is empty, use the update we just performed
- if ( ! $next_user_core_update )
- $next_user_core_update = $core_update;
- $newer_version_available = ( 'upgrade' == $next_user_core_update->response && version_compare( $next_user_core_update->version, $core_update->version, '>' ) );
-
- /**
- * Filter whether to send an email following an automatic background core update.
- *
- * @since 3.7.0
- *
- * @param bool $send Whether to send the email. Default true.
- * @param string $type The type of email to send. Can be one of
- * 'success', 'fail', 'critical'.
- * @param object $core_update The update offer that was attempted.
- * @param mixed $result The result for the core update. Can be WP_Error.
- */
- if ( 'manual' !== $type && ! apply_filters( 'auto_core_update_send_email', true, $type, $core_update, $result ) )
- return;
-
- switch ( $type ) {
- case 'success' : // We updated.
- /* translators: 1: Site name, 2: WordPress version number. */
- $subject = __( '[%1$s] Your site has updated to WordPress %2$s' );
- break;
-
- case 'fail' : // We tried to update but couldn't.
- case 'manual' : // We can't update (and made no attempt).
- /* translators: 1: Site name, 2: WordPress version number. */
- $subject = __( '[%1$s] WordPress %2$s is available. Please update!' );
- break;
-
- case 'critical' : // We tried to update, started to copy files, then things went wrong.
- /* translators: 1: Site name. */
- $subject = __( '[%1$s] URGENT: Your site may be down due to a failed update' );
- break;
-
- default :
- return;
- }
-
- // If the auto update is not to the latest version, say that the current version of WP is available instead.
- $version = 'success' === $type ? $core_update->current : $next_user_core_update->current;
- $subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $version );
-
- $body = '';
-
- switch ( $type ) {
- case 'success' :
- $body .= sprintf( __( 'Howdy! Your site at %1$s has been updated automatically to WordPress %2$s.' ), home_url(), $core_update->current );
- $body .= "\n\n";
- if ( ! $newer_version_available )
- $body .= __( 'No further action is needed on your part.' ) . ' ';
-
- // Can only reference the About screen if their update was successful.
- list( $about_version ) = explode( '-', $core_update->current, 2 );
- $body .= sprintf( __( "For more on version %s, see the About WordPress screen:" ), $about_version );
- $body .= "\n" . admin_url( 'about.php' );
-
- if ( $newer_version_available ) {
- $body .= "\n\n" . sprintf( __( 'WordPress %s is also now available.' ), $next_user_core_update->current ) . ' ';
- $body .= __( 'Updating is easy and only takes a few moments:' );
- $body .= "\n" . network_admin_url( 'update-core.php' );
- }
-
- break;
-
- case 'fail' :
- case 'manual' :
- $body .= sprintf( __( 'Please update your site at %1$s to WordPress %2$s.' ), home_url(), $next_user_core_update->current );
-
- $body .= "\n\n";
-
- // Don't show this message if there is a newer version available.
- // Potential for confusion, and also not useful for them to know at this point.
- if ( 'fail' == $type && ! $newer_version_available )
- $body .= __( 'We tried but were unable to update your site automatically.' ) . ' ';
-
- $body .= __( 'Updating is easy and only takes a few moments:' );
- $body .= "\n" . network_admin_url( 'update-core.php' );
- break;
-
- case 'critical' :
- if ( $newer_version_available )
- $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update WordPress to version %2$s.' ), home_url(), $core_update->current );
- else
- $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update to the latest version of WordPress, %2$s.' ), home_url(), $core_update->current );
-
- $body .= "\n\n" . __( "This means your site may be offline or broken. Don't panic; this can be fixed." );
-
- $body .= "\n\n" . __( "Please check out your site now. It's possible that everything is working. If it says you need to update, you should do so:" );
- $body .= "\n" . network_admin_url( 'update-core.php' );
- break;
- }
-
- $critical_support = 'critical' === $type && ! empty( $core_update->support_email );
- if ( $critical_support ) {
- // Support offer if available.
- $body .= "\n\n" . sprintf( __( "The WordPress team is willing to help you. Forward this email to %s and the team will work with you to make sure your site is working." ), $core_update->support_email );
- } else {
- // Add a note about the support forums.
- $body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
- $body .= "\n" . __( 'https://wordpress.org/support/' );
- }
-
- // Updates are important!
- if ( $type != 'success' || $newer_version_available ) {
- $body .= "\n\n" . __( 'Keeping your site updated is important for security. It also makes the internet a safer place for you and your readers.' );
- }
-
- if ( $critical_support ) {
- $body .= " " . __( "If you reach out to us, we'll also ensure you'll never have this problem again." );
- }
-
- // If things are successful and we're now on the latest, mention plugins and themes if any are out of date.
- if ( $type == 'success' && ! $newer_version_available && ( get_plugin_updates() || get_theme_updates() ) ) {
- $body .= "\n\n" . __( 'You also have some plugins or themes with updates available. Update them now:' );
- $body .= "\n" . network_admin_url();
- }
-
- $body .= "\n\n" . __( 'The WordPress Team' ) . "\n";
-
- if ( 'critical' == $type && is_wp_error( $result ) ) {
- $body .= "\n***\n\n";
- $body .= sprintf( __( 'Your site was running version %s.' ), $GLOBALS['wp_version'] );
- $body .= ' ' . __( 'We have some data that describes the error your site encountered.' );
- $body .= ' ' . __( 'Your hosting company, support forum volunteers, or a friendly developer may be able to use this information to help you:' );
-
- // If we had a rollback and we're still critical, then the rollback failed too.
- // Loop through all errors (the main WP_Error, the update result, the rollback result) for code, data, etc.
- if ( 'rollback_was_required' == $result->get_error_code() )
- $errors = array( $result, $result->get_error_data()->update, $result->get_error_data()->rollback );
- else
- $errors = array( $result );
-
- foreach ( $errors as $error ) {
- if ( ! is_wp_error( $error ) )
- continue;
- $error_code = $error->get_error_code();
- $body .= "\n\n" . sprintf( __( "Error code: %s" ), $error_code );
- if ( 'rollback_was_required' == $error_code )
- continue;
- if ( $error->get_error_message() )
- $body .= "\n" . $error->get_error_message();
- $error_data = $error->get_error_data();
- if ( $error_data )
- $body .= "\n" . implode( ', ', (array) $error_data );
- }
- $body .= "\n";
- }
-
- $to = get_site_option( 'admin_email' );
- $headers = '';
-
- $email = compact( 'to', 'subject', 'body', 'headers' );
-
- /**
- * Filter the email sent following an automatic background core update.
- *
- * @since 3.7.0
- *
- * @param array $email {
- * Array of email arguments that will be passed to wp_mail().
- *
- * @type string $to The email recipient. An array of emails
- * can be returned, as handled by wp_mail().
- * @type string $subject The email's subject.
- * @type string $body The email message body.
- * @type string $headers Any email headers, defaults to no headers.
- * }
- * @param string $type The type of email being sent. Can be one of
- * 'success', 'fail', 'manual', 'critical'.
- * @param object $core_update The update offer that was attempted.
- * @param mixed $result The result for the core update. Can be WP_Error.
- */
- $email = apply_filters( 'auto_core_update_email', $email, $type, $core_update, $result );
-
- wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
- }
-
- /**
- * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
- *
- * @since 3.7.0
- * @access protected
- */
- protected function send_debug_email() {
- $update_count = 0;
- foreach ( $this->update_results as $type => $updates )
- $update_count += count( $updates );
-
- $body = array();
- $failures = 0;
-
- $body[] = sprintf( __( 'WordPress site: %s' ), network_home_url( '/' ) );
-
- // Core
- if ( isset( $this->update_results['core'] ) ) {
- $result = $this->update_results['core'][0];
- if ( $result->result && ! is_wp_error( $result->result ) ) {
- $body[] = sprintf( __( 'SUCCESS: WordPress was successfully updated to %s' ), $result->name );
- } else {
- $body[] = sprintf( __( 'FAILED: WordPress failed to update to %s' ), $result->name );
- $failures++;
- }
- $body[] = '';
- }
-
- // Plugins, Themes, Translations
- foreach ( array( 'plugin', 'theme', 'translation' ) as $type ) {
- if ( ! isset( $this->update_results[ $type ] ) )
- continue;
- $success_items = wp_list_filter( $this->update_results[ $type ], array( 'result' => true ) );
- if ( $success_items ) {
- $messages = array(
- 'plugin' => __( 'The following plugins were successfully updated:' ),
- 'theme' => __( 'The following themes were successfully updated:' ),
- 'translation' => __( 'The following translations were successfully updated:' ),
- );
-
- $body[] = $messages[ $type ];
- foreach ( wp_list_pluck( $success_items, 'name' ) as $name ) {
- $body[] = ' * ' . sprintf( __( 'SUCCESS: %s' ), $name );
- }
- }
- if ( $success_items != $this->update_results[ $type ] ) {
- // Failed updates
- $messages = array(
- 'plugin' => __( 'The following plugins failed to update:' ),
- 'theme' => __( 'The following themes failed to update:' ),
- 'translation' => __( 'The following translations failed to update:' ),
- );
-
- $body[] = $messages[ $type ];
- foreach ( $this->update_results[ $type ] as $item ) {
- if ( ! $item->result || is_wp_error( $item->result ) ) {
- $body[] = ' * ' . sprintf( __( 'FAILED: %s' ), $item->name );
- $failures++;
- }
- }
- }
- $body[] = '';
- }
-
- $site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
- if ( $failures ) {
- $body[] = trim( __(
-"BETA TESTING?
-=============
-
-This debugging email is sent when you are using a development version of WordPress.
-
-If you think these failures might be due to a bug in WordPress, could you report it?
- * Open a thread in the support forums: https://wordpress.org/support/forum/alphabeta
- * Or, if you're comfortable writing a bug report: https://core.trac.wordpress.org/
-
-Thanks! -- The WordPress Team" ) );
- $body[] = '';
-
- $subject = sprintf( __( '[%s] There were failures during background updates' ), $site_title );
- } else {
- $subject = sprintf( __( '[%s] Background updates have finished' ), $site_title );
- }
-
- $body[] = trim( __(
-'UPDATE LOG
-==========' ) );
- $body[] = '';
-
- foreach ( array( 'core', 'plugin', 'theme', 'translation' ) as $type ) {
- if ( ! isset( $this->update_results[ $type ] ) )
- continue;
- foreach ( $this->update_results[ $type ] as $update ) {
- $body[] = $update->name;
- $body[] = str_repeat( '-', strlen( $update->name ) );
- foreach ( $update->messages as $message )
- $body[] = " " . html_entity_decode( str_replace( '…', '...', $message ) );
- if ( is_wp_error( $update->result ) ) {
- $results = array( 'update' => $update->result );
- // If we rolled back, we want to know an error that occurred then too.
- if ( 'rollback_was_required' === $update->result->get_error_code() )
- $results = (array) $update->result->get_error_data();
- foreach ( $results as $result_type => $result ) {
- if ( ! is_wp_error( $result ) )
- continue;
-
- if ( 'rollback' === $result_type ) {
- /* translators: 1: Error code, 2: Error message. */
- $body[] = ' ' . sprintf( __( 'Rollback Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
- } else {
- /* translators: 1: Error code, 2: Error message. */
- $body[] = ' ' . sprintf( __( 'Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
- }
-
- if ( $result->get_error_data() )
- $body[] = ' ' . implode( ', ', (array) $result->get_error_data() );
- }
- }
- $body[] = '';
- }
- }
-
- $email = array(
- 'to' => get_site_option( 'admin_email' ),
- 'subject' => $subject,
- 'body' => implode( "\n", $body ),
- 'headers' => ''
- );
-
- /**
- * Filter the debug email that can be sent following an automatic
- * background core update.
- *
- * @since 3.8.0
- *
- * @param array $email {
- * Array of email arguments that will be passed to wp_mail().
- *
- * @type string $to The email recipient. An array of emails
- * can be returned, as handled by wp_mail().
- * @type string $subject Email subject.
- * @type string $body Email message body.
- * @type string $headers Any email headers. Default empty.
- * }
- * @param int $failures The number of failures encountered while upgrading.
- * @param mixed $results The results of all attempted updates.
- */
- $email = apply_filters( 'automatic_updates_debug_email', $email, $failures, $this->update_results );
-
- wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
- }
-}
+/** WP_Automatic_Updater class */
+require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
diff --git a/wp-admin/includes/class-wp-users-list-table.php b/wp-admin/includes/class-wp-users-list-table.php
index 9e26867d..80720b6c 100644
--- a/wp-admin/includes/class-wp-users-list-table.php
+++ b/wp-admin/includes/class-wp-users-list-table.php
@@ -125,7 +125,7 @@ class WP_Users_List_Table extends WP_List_Table {
$args['order'] = $_REQUEST['order'];
/**
- * Filter the query arguments used to retrieve users for the current users list table.
+ * Filters the query arguments used to retrieve users for the current users list table.
*
* @since 4.4.0
*
@@ -160,7 +160,7 @@ class WP_Users_List_Table extends WP_List_Table {
* with this table.
*
* Provides a list of roles and user count for that role for easy
- * filtering of the user table.
+ * Filtersing of the user table.
*
* @since 3.1.0
* @access protected
@@ -275,8 +275,11 @@ class WP_Users_List_Table extends WP_List_Table {
* in the Users list table.
*
* @since 3.5.0
+ * @since 4.6.0 The `$which` parameter was added.
+ *
+ * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
*/
- do_action( 'restrict_manage_users' );
+ do_action( 'restrict_manage_users', $which );
echo '' . __( 'You do not have sufficient permissions to add users to this network.' ) . '
', + '' . __( 'Sorry, you are not allowed to add users to this network.' ) . '
', 403 ); } } elseif ( ! current_user_can( 'create_users' ) ) { wp_die( '' . __( 'You are not allowed to create users.' ) . '
', + '' . __( 'Sorry, you are not allowed to create users.' ) . '
', 403 ); } @@ -53,7 +53,7 @@ if ( isset($_REQUEST['action']) && 'adduser' == $_REQUEST['action'] ) { if ( ! current_user_can( 'promote_user', $user_details->ID ) ) { wp_die( '' . __( 'You do not have sufficient permissions to add users to this network.' ) . '
', + '' . __( 'Sorry, you are not allowed to add users to this network.' ) . '
', 403 ); } @@ -107,7 +107,7 @@ Please click the following link to confirm the invite: if ( ! current_user_can( 'create_users' ) ) { wp_die( '' . __( 'You are not allowed to create users.' ) . '
', + '' . __( 'Sorry, you are not allowed to create users.' ) . '
', 403 ); } @@ -133,7 +133,7 @@ Please click the following link to confirm the invite: $add_user_errors = $user_details[ 'errors' ]; } else { /** - * Filter the user_login, also known as the username, before it is added to the site. + * Filters the user_login, also known as the username, before it is added to the site. * * @since 2.0.3 * @@ -148,7 +148,7 @@ Please click the following link to confirm the invite: if ( isset( $_POST[ 'noconfirmation' ] ) && current_user_can( 'manage_network_users' ) ) { $key = $wpdb->get_var( $wpdb->prepare( "SELECT activation_key FROM {$wpdb->signups} WHERE user_login = %s AND user_email = %s", $new_user_login, $new_user_email ) ); $new_user = wpmu_activate_signup( $key ); - if ( ! is_wp_error( $new_user ) ) { + if ( is_wp_error( $new_user ) ) { $redirect = add_query_arg( array( 'update' => 'addnoconfirmation' ), 'user-new.php' ); } else { $redirect = add_query_arg( array( 'update' => 'addnoconfirmation', 'user_id' => $new_user['user_id'] ), 'user-new.php' ); @@ -175,8 +175,9 @@ if ( is_multisite() ) { $help .= '' . __('Because this is a multisite installation, you may add accounts that already exist on the Network by specifying a username or email, and defining a role. For more options, such as specifying a password, you have to be a Network Administrator and use the hover link under an existing user’s name to Edit the user profile under Network Admin > All Users.') . '
' . '' . __('New users will receive an email letting them know they’ve been added as a user for your site. This email will also contain their password. Check the box if you don’t want the user to receive a welcome email.') . '
'; } else { - $help .= '' . __('You must assign a password to the new user, which they can change after logging in. The username, however, cannot be changed.') . '
' . - '' . __('New users will receive an email letting them know they’ve been added as a user for your site. By default, this email will also contain their password. Uncheck the box if you don’t want the password to be included in the welcome email.') . '
'; + $help .= '' . __('New users are automatically assigned a password, which they can change after logging in. You can view or edit the assigned password by clicking the Show Password button. The username cannot be changed once the user has been added.') . '
' . + + '' . __('By default, new users will receive an email letting them know they’ve been added as a user for your site. This email will also contain a password reset link. Uncheck the box if you don’t want to send the new user a welcome email.') . '
'; } $help .= '' . __('Remember to click the Add New User button at the bottom of this screen when you are finished.') . '
'; @@ -210,7 +211,7 @@ wp_enqueue_script('wp-ajax-response'); wp_enqueue_script( 'user-profile' ); /** - * Filter whether to enable user auto-complete for non-super admins in Multisite. + * Filters whether to enable user auto-complete for non-super admins in Multisite. * * @since 3.4.0 * diff --git a/wp-admin/user/admin.php b/wp-admin/user/admin.php index 14452458..3d5063c0 100644 --- a/wp-admin/user/admin.php +++ b/wp-admin/user/admin.php @@ -18,7 +18,7 @@ if ( ! is_multisite() ) { $redirect_user_admin_request = ( ( $current_blog->domain != $current_site->domain ) || ( $current_blog->path != $current_site->path ) ); /** - * Filter whether to redirect the request to the User Admin in Multisite. + * Filters whether to redirect the request to the User Admin in Multisite. * * @since 3.2.0 * diff --git a/wp-admin/users.php b/wp-admin/users.php index 789f34c9..194ced94 100644 --- a/wp-admin/users.php +++ b/wp-admin/users.php @@ -13,7 +13,7 @@ require_once( dirname( __FILE__ ) . '/admin.php' ); if ( ! current_user_can( 'list_users' ) ) { wp_die( '' . __( 'You are not allowed to browse users.' ) . '
', + '' . __( 'Sorry, you are not allowed to browse users.' ) . '
', 403 ); } @@ -39,7 +39,7 @@ get_current_screen()->add_help_tab( array( 'content' => '' . __('You can customize the display of this screen in a number of ways:') . '
' . '' . __( 'You are not allowed to edit theme options on this site.' ) . '
', + '' . __( 'Sorry, you are not allowed to edit theme options on this site.' ) . '
', 403 ); } @@ -357,7 +357,7 @@ require_once( ABSPATH . 'wp-admin/admin-header.php' ); ?> ), admin_url( 'customize.php' ) ) ), - __( 'Manage in Customizer' ) + __( 'Manage with Live Preview' ) ); } ?> diff --git a/wp-comments-post.php b/wp-comments-post.php index 4fb249ba..4e9f1fcf 100644 --- a/wp-comments-post.php +++ b/wp-comments-post.php @@ -42,7 +42,7 @@ do_action( 'set_comment_cookies', $comment, $user ); $location = empty( $_POST['redirect_to'] ) ? get_comment_link( $comment ) : $_POST['redirect_to'] . '#comment-' . $comment->comment_ID; /** - * Filter the location URI to send the commenter after posting. + * Filters the location URI to send the commenter after posting. * * @since 2.0.5 * diff --git a/wp-content/themes/twentyfifteen/functions.php b/wp-content/themes/twentyfifteen/functions.php index 50cce934..056a3613 100644 --- a/wp-content/themes/twentyfifteen/functions.php +++ b/wp-content/themes/twentyfifteen/functions.php @@ -55,11 +55,11 @@ function twentyfifteen_setup() { /* * Make theme available for translation. - * Translations can be filed in the /languages/ directory. + * Translations can be filed at WordPress.org. See: https://translate.wordpress.org/projects/wp-themes/twentyfifteen * If you're building a theme based on twentyfifteen, use a find and replace * to change 'twentyfifteen' to the name of your theme in all the template files */ - load_theme_textdomain( 'twentyfifteen', get_template_directory() . '/languages' ); + load_theme_textdomain( 'twentyfifteen' ); // Add default posts and comments RSS feed links to head. add_theme_support( 'automatic-feed-links' ); diff --git a/wp-content/themes/twentyfifteen/languages/twentyfifteen.pot b/wp-content/themes/twentyfifteen/languages/twentyfifteen.pot deleted file mode 100644 index b01d4271..00000000 --- a/wp-content/themes/twentyfifteen/languages/twentyfifteen.pot +++ /dev/null @@ -1,321 +0,0 @@ -# Copyright (C) 2016 the WordPress team -# This file is distributed under the GNU General Public License v2 or later. -msgid "" -msgstr "" -"Project-Id-Version: Twenty Fifteen 1.5\n" -"Report-Msgid-Bugs-To: https://wordpress.org/support/theme/twentyfifteen\n" -"POT-Creation-Date: 2016-04-05 09:48:39+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAMEget_the_author()
'
@@ -88,7 +88,7 @@ function get_the_modified_author() {
$last_user = get_userdata($last_id);
/**
- * Filter the display name of the author who last edited the current post.
+ * Filters the display name of the author who last edited the current post.
*
* @since 2.8.0
*
@@ -137,7 +137,7 @@ function get_the_author_meta( $field = '', $user_id = false ) {
$value = isset( $authordata->$field ) ? $authordata->$field : '';
/**
- * Filter the value of the requested user metadata.
+ * Filters the value of the requested user metadata.
*
* The filter name is dynamic and depends on the $field parameter of the function.
*
@@ -258,7 +258,7 @@ function get_the_author_posts_link() {
);
/**
- * Filter the link to the author page of the author of the current post.
+ * Filters the link to the author page of the author of the current post.
*
* @since 2.9.0
*
@@ -277,7 +277,7 @@ function get_the_author_posts_link() {
*/
function the_author_posts_link( $deprecated = '' ) {
if ( ! empty( $deprecated ) ) {
- _deprecated_argument( __FUNCTION__, '2.1' );
+ _deprecated_argument( __FUNCTION__, '2.1.0' );
}
echo get_the_author_posts_link();
}
@@ -312,7 +312,7 @@ function get_author_posts_url( $author_id, $author_nicename = '' ) {
}
/**
- * Filter the URL to the author's page.
+ * Filters the URL to the author's page.
*
* @since 2.1.0
*
@@ -337,26 +337,26 @@ function get_author_posts_url( $author_id, $author_nicename = '' ) {
* @param string|array $args {
* Optional. Array or string of default arguments.
*
- * @type string $orderby How to sort the authors. Accepts 'nicename', 'email', 'url', 'registered',
- * 'user_nicename', 'user_email', 'user_url', 'user_registered', 'name',
- * 'display_name', 'post_count', 'ID', 'meta_value', 'user_login'. Default 'name'.
- * @type string $order Sorting direction for $orderby. Accepts 'ASC', 'DESC'. Default 'ASC'.
- * @type int $number Maximum authors to return or display. Default empty (all authors).
- * @type bool $optioncount Show the count in parenthesis next to the author's name. Default false.
- * @type bool $exclude_admin Whether to exclude the 'admin' account, if it exists. Default false.
- * @type bool $show_fullname Whether to show the author's full name. Default false.
- * @type bool $hide_empty Whether to hide any authors with no posts. Default true.
- * @type string $feed If not empty, show a link to the author's feed and use this text as the alt
- * parameter of the link. Default empty.
- * @type string $feed_image If not empty, show a link to the author's feed and use this image URL as
- * clickable anchor. Default empty.
- * @type string $feed_type The feed type to link to, such as 'rss2'. Defaults to default feed type.
- * @type bool $echo Whether to output the result or instead return it. Default true.
- * @type string $style If 'list', each author is wrapped in an `