diff -r 3d4e9c994f10 -r a86126ab1dd4 wp/wp-admin/includes/theme.php --- a/wp/wp-admin/includes/theme.php Tue Oct 22 16:11:46 2019 +0200 +++ b/wp/wp-admin/includes/theme.php Tue Dec 15 13:49:49 2020 +0100 @@ -35,9 +35,9 @@ if ( false === $credentials ) { if ( ! empty( $data ) ) { - include_once( ABSPATH . 'wp-admin/admin-header.php' ); + require_once ABSPATH . 'wp-admin/admin-header.php'; echo $data; - include( ABSPATH . 'wp-admin/admin-footer.php' ); + require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } return; @@ -45,13 +45,14 @@ if ( ! WP_Filesystem( $credentials ) ) { ob_start(); - request_filesystem_credentials( $redirect, '', true ); // Failed to connect, Error and request again. + // Failed to connect. Error and request again. + request_filesystem_credentials( $redirect, '', true ); $data = ob_get_clean(); if ( ! empty( $data ) ) { - include_once( ABSPATH . 'wp-admin/admin-header.php' ); + require_once ABSPATH . 'wp-admin/admin-header.php'; echo $data; - include( ABSPATH . 'wp-admin/admin-footer.php' ); + require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } return; @@ -76,7 +77,11 @@ $deleted = $wp_filesystem->delete( $theme_dir, true ); if ( ! $deleted ) { - return new WP_Error( 'could_not_remove_theme', sprintf( __( 'Could not fully remove the theme %s.' ), $stylesheet ) ); + return new WP_Error( + 'could_not_remove_theme', + /* translators: %s: Theme name. */ + sprintf( __( 'Could not fully remove the theme %s.' ), $stylesheet ) + ); } $theme_translations = wp_get_installed_translations( 'themes' ); @@ -108,14 +113,14 @@ } /** - * Get the Page Templates available in this theme + * Gets the page templates available in this theme. * * @since 1.5.0 * @since 4.7.0 Added the `$post_type` parameter. * * @param WP_Post|null $post Optional. The post being edited, provided for context. * @param string $post_type Optional. Post type to get the templates for. Default 'page'. - * @return array Key is the template name, value is the filename of the template + * @return string[] Array of template file names keyed by the template header name. */ function get_page_templates( $post = null, $post_type = 'page' ) { return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) ); @@ -141,6 +146,7 @@ * Will display link, if there is an update available. * * @since 2.7.0 + * * @see get_theme_update_available() * * @param WP_Theme $theme Theme data object. @@ -156,10 +162,8 @@ * * @since 3.8.0 * - * @staticvar object $themes_update - * * @param WP_Theme $theme WP_Theme object. - * @return false|string HTML for the update link, or false if invalid info was passed. + * @return string|false HTML for the update link, or false if invalid info was passed. */ function get_theme_update_available( $theme ) { static $themes_update = null; @@ -190,53 +194,53 @@ 'height' => 800, ), $update['url'] - ); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list. + ); // Theme browser inside WP? Replace this. Also, theme preview JS will override this on the available list. $update_url = wp_nonce_url( admin_url( 'update.php?action=upgrade-theme&theme=' . urlencode( $stylesheet ) ), 'upgrade-theme_' . $stylesheet ); if ( ! is_multisite() ) { if ( ! current_user_can( 'update_themes' ) ) { - /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number */ $html = sprintf( + /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */ '

' . __( 'There is a new version of %1$s available. View version %4$s details.' ) . '

', $theme_name, esc_url( $details_url ), sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', - /* translators: 1: theme name, 2: version number */ + /* translators: 1: Theme name, 2: Version number. */ esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) ), $update['new_version'] ); } elseif ( empty( $update['package'] ) ) { - /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number */ $html = sprintf( + /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */ '

' . __( 'There is a new version of %1$s available. View version %4$s details. Automatic update is unavailable for this theme.' ) . '

', $theme_name, esc_url( $details_url ), sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', - /* translators: 1: theme name, 2: version number */ + /* translators: 1: Theme name, 2: Version number. */ esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) ), $update['new_version'] ); } else { - /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number, 5: update URL, 6: additional link attributes */ $html = sprintf( + /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */ '

' . __( 'There is a new version of %1$s available. View version %4$s details or update now.' ) . '

', $theme_name, esc_url( $details_url ), sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', - /* translators: 1: theme name, 2: version number */ + /* translators: 1: Theme name, 2: Version number. */ esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) ), $update['new_version'], $update_url, sprintf( 'aria-label="%s" id="update-theme" data-slug="%s"', - /* translators: %s: theme name */ - esc_attr( sprintf( __( 'Update %s now' ), $theme_name ) ), + /* translators: %s: Theme name. */ + esc_attr( sprintf( _x( 'Update %s now', 'theme' ), $theme_name ) ), $stylesheet ) ); @@ -251,12 +255,36 @@ * Retrieve list of WordPress theme features (aka theme tags). * * @since 3.1.0 + * @since 3.2.0 Added 'Gray' color and 'Featured Image Header', 'Featured Images', + * 'Full Width Template', and 'Post Formats' features. + * @since 3.5.0 Added 'Flexible Header' feature. + * @since 3.8.0 Renamed 'Width' filter to 'Layout'. + * @since 3.8.0 Renamed 'Fixed Width' and 'Flexible Width' options + * to 'Fixed Layout' and 'Fluid Layout'. + * @since 3.8.0 Added 'Accessibility Ready' feature and 'Responsive Layout' option. + * @since 3.9.0 Combined 'Layout' and 'Columns' filters. + * @since 4.6.0 Removed 'Colors' filter. + * @since 4.6.0 Added 'Grid Layout' option. + * Removed 'Fixed Layout', 'Fluid Layout', and 'Responsive Layout' options. + * @since 4.6.0 Added 'Custom Logo' and 'Footer Widgets' features. + * Removed 'Blavatar' feature. + * @since 4.6.0 Added 'Blog', 'E-Commerce', 'Education', 'Entertainment', 'Food & Drink', + * 'Holiday', 'News', 'Photography', and 'Portfolio' subjects. + * Removed 'Photoblogging' and 'Seasonal' subjects. + * @since 4.9.0 Reordered the filters from 'Layout', 'Features', 'Subject' + * to 'Subject', 'Features', 'Layout'. + * @since 4.9.0 Removed 'BuddyPress', 'Custom Menu', 'Flexible Header', + * 'Front Page Posting', 'Microformats', 'RTL Language Support', + * 'Threaded Comments', and 'Translation Ready' features. + * @since 5.5.0 Added 'Block Editor Patterns', 'Block Editor Styles', + * and 'Full Site Editing' features. + * @since 5.5.0 Added 'Wide Blocks' layout option. * * @param bool $api Optional. Whether try to fetch tags from the WordPress.org API. Defaults to true. * @return array Array of features keyed by category with translations keyed by slug. */ function get_theme_feature_list( $api = true ) { - // Hard-coded list is used if api not accessible. + // Hard-coded list is used if API is not accessible. $features = array( __( 'Subject' ) => array( @@ -273,6 +301,8 @@ __( 'Features' ) => array( 'accessibility-ready' => __( 'Accessibility Ready' ), + 'block-patterns' => __( 'Block Editor Patterns' ), + 'block-styles' => __( 'Block Editor Styles' ), 'custom-background' => __( 'Custom Background' ), 'custom-colors' => __( 'Custom Colors' ), 'custom-header' => __( 'Custom Header' ), @@ -281,6 +311,7 @@ 'featured-image-header' => __( 'Featured Image Header' ), 'featured-images' => __( 'Featured Images' ), 'footer-widgets' => __( 'Footer Widgets' ), + 'full-site-editing' => __( 'Full Site Editing' ), 'full-width-template' => __( 'Full Width Template' ), 'post-formats' => __( 'Post Formats' ), 'sticky-post' => __( 'Sticky Post' ), @@ -295,6 +326,7 @@ 'four-columns' => __( 'Four Columns' ), 'left-sidebar' => __( 'Left Sidebar' ), 'right-sidebar' => __( 'Right Sidebar' ), + 'wide-blocks' => __( 'Wide Blocks' ), ), ); @@ -303,7 +335,8 @@ return $features; } - if ( ! $feature_list = get_site_transient( 'wporg_theme_feature_list' ) ) { + $feature_list = get_site_transient( 'wporg_theme_feature_list' ); + if ( ! $feature_list ) { set_site_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS ); } @@ -326,12 +359,14 @@ 'Subject' => __( 'Subject' ), ); - // Loop over the wporg canonical list and apply translations $wporg_features = array(); + + // Loop over the wp.org canonical list and apply translations. foreach ( (array) $feature_list as $feature_category => $feature_items ) { if ( isset( $category_translations[ $feature_category ] ) ) { $feature_category = $category_translations[ $feature_category ]; } + $wporg_features[ $feature_category ] = array(); foreach ( $feature_items as $feature ) { @@ -428,14 +463,14 @@ * for more information on the make-up of possible return objects depending on the value of `$action`. */ function themes_api( $action, $args = array() ) { - // include an unmodified $wp_version - include( ABSPATH . WPINC . '/version.php' ); + // Include an unmodified $wp_version. + require ABSPATH . WPINC . '/version.php'; if ( is_array( $args ) ) { $args = (object) $args; } - if ( 'query_themes' == $action ) { + if ( 'query_themes' === $action ) { if ( ! isset( $args->per_page ) ) { $args->per_page = 24; } @@ -446,7 +481,7 @@ } if ( ! isset( $args->wp_version ) ) { - $args->wp_version = substr( $wp_version, 0, 3 ); // X.y + $args->wp_version = substr( $wp_version, 0, 3 ); // x.y } /** @@ -490,7 +525,8 @@ ); $http_url = $url; - if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) { + $ssl = wp_http_supports( array( 'ssl' ) ); + if ( $ssl ) { $url = set_url_scheme( $url, 'https' ); } @@ -503,9 +539,9 @@ if ( ! wp_doing_ajax() ) { trigger_error( sprintf( - /* translators: %s: support forums URL */ + /* translators: %s: Support forums URL. */ __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), - __( 'https://wordpress.org/support/' ) + __( 'https://wordpress.org/support/forums/' ) ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE ); @@ -517,9 +553,9 @@ $res = new WP_Error( 'themes_api_failed', sprintf( - /* translators: %s: support forums URL */ + /* translators: %s: Support forums URL. */ __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), - __( 'https://wordpress.org/support/' ) + __( 'https://wordpress.org/support/forums/' ) ), $request->get_error_message() ); @@ -532,9 +568,9 @@ $res = new WP_Error( 'themes_api_failed', sprintf( - /* translators: %s: support forums URL */ + /* translators: %s: Support forums URL. */ __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), - __( 'https://wordpress.org/support/' ) + __( 'https://wordpress.org/support/forums/' ) ), wp_remote_retrieve_body( $request ) ); @@ -546,13 +582,13 @@ } // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects. - if ( 'query_themes' == $action ) { + if ( 'query_themes' === $action ) { foreach ( $res->themes as $i => $theme ) { $res->themes[ $i ] = (object) $theme; } } // Back-compat for info/1.2 API, downgrade the feature_list result back to an array. - if ( 'feature_list' == $action ) { + if ( 'feature_list' === $action ) { $res = (array) $res; } } @@ -611,18 +647,24 @@ } } - $updates = array(); + $updates = array(); + $no_updates = array(); if ( current_user_can( 'update_themes' ) ) { $updates_transient = get_site_transient( 'update_themes' ); if ( isset( $updates_transient->response ) ) { $updates = $updates_transient->response; } + if ( isset( $updates_transient->no_update ) ) { + $no_updates = $updates_transient->no_update; + } } WP_Theme::sort_by_name( $themes ); $parents = array(); + $auto_updates = (array) get_site_option( 'auto_update_themes', array() ); + foreach ( $themes as $theme ) { $slug = $theme->get_stylesheet(); $encoded_slug = urlencode( $slug ); @@ -646,29 +688,75 @@ ); } + $update_requires_wp = isset( $updates[ $slug ]['requires'] ) ? $updates[ $slug ]['requires'] : null; + $update_requires_php = isset( $updates[ $slug ]['requires_php'] ) ? $updates[ $slug ]['requires_php'] : null; + + $auto_update = in_array( $slug, $auto_updates, true ); + $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update'; + + if ( isset( $updates[ $slug ] ) ) { + $auto_update_supported = true; + $auto_update_filter_payload = (object) $updates[ $slug ]; + } elseif ( isset( $no_updates[ $slug ] ) ) { + $auto_update_supported = true; + $auto_update_filter_payload = (object) $no_updates[ $slug ]; + } else { + $auto_update_supported = false; + /* + * Create the expected payload for the auto_update_theme filter, this is the same data + * as contained within $updates or $no_updates but used when the Theme is not known. + */ + $auto_update_filter_payload = (object) array( + 'theme' => $slug, + 'new_version' => $theme->get( 'Version' ), + 'url' => '', + 'package' => '', + 'requires' => $theme->get( 'RequiresWP' ), + 'requires_php' => $theme->get( 'RequiresPHP' ), + ); + } + + $type = 'theme'; + /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */ + $auto_update_forced = apply_filters( "auto_update_{$type}", null, $auto_update_filter_payload ); + $prepared_themes[ $slug ] = array( - 'id' => $slug, - 'name' => $theme->display( 'Name' ), - 'screenshot' => array( $theme->get_screenshot() ), // @todo multiple - 'description' => $theme->display( 'Description' ), - 'author' => $theme->display( 'Author', false, true ), - 'authorAndUri' => $theme->display( 'Author' ), - 'version' => $theme->display( 'Version' ), - 'tags' => $theme->display( 'Tags' ), - 'parent' => $parent, - 'active' => $slug === $current_theme, - 'hasUpdate' => isset( $updates[ $slug ] ), - 'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ), - 'update' => get_theme_update_available( $theme ), - 'actions' => array( - 'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null, - 'customize' => $customize_action, - 'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null, + 'id' => $slug, + 'name' => $theme->display( 'Name' ), + 'screenshot' => array( $theme->get_screenshot() ), // @todo Multiple screenshots. + 'description' => $theme->display( 'Description' ), + 'author' => $theme->display( 'Author', false, true ), + 'authorAndUri' => $theme->display( 'Author' ), + 'tags' => $theme->display( 'Tags' ), + 'version' => $theme->get( 'Version' ), + 'compatibleWP' => is_wp_version_compatible( $theme->get( 'RequiresWP' ) ), + 'compatiblePHP' => is_php_version_compatible( $theme->get( 'RequiresPHP' ) ), + 'updateResponse' => array( + 'compatibleWP' => is_wp_version_compatible( $update_requires_wp ), + 'compatiblePHP' => is_php_version_compatible( $update_requires_php ), + ), + 'parent' => $parent, + 'active' => $slug === $current_theme, + 'hasUpdate' => isset( $updates[ $slug ] ), + 'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ), + 'update' => get_theme_update_available( $theme ), + 'autoupdate' => array( + 'enabled' => $auto_update || $auto_update_forced, + 'supported' => $auto_update_supported, + 'forced' => $auto_update_forced, + ), + 'actions' => array( + 'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null, + 'customize' => $customize_action, + 'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null, + 'autoupdate' => wp_is_auto_update_enabled_for_type( 'theme' ) && ! is_multisite() && current_user_can( 'update_themes' ) + ? wp_nonce_url( admin_url( 'themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug ), 'updates' ) + : null, ), ); } - // Remove 'delete' action if theme has an active child + // Remove 'delete' action if theme has an active child. if ( ! empty( $parents ) && array_key_exists( $current_theme, $parents ) ) { unset( $prepared_themes[ $parents[ $current_theme ] ]['actions']['delete'] ); } @@ -680,7 +768,7 @@ * * @since 3.8.0 * - * @param array $prepared_themes Array of themes. + * @param array $prepared_themes Array of theme data. */ $prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes ); $prepared_themes = array_values( $prepared_themes ); @@ -715,8 +803,18 @@ <# if ( data.active ) { #> <# } #> -

{{{ data.name }}}

-

+

{{{ data.name }}} + +

+

+ +

<# if ( data.stars && 0 != data.num_ratings ) { #>
@@ -725,9 +823,9 @@ %2$s', - /* translators: %s: number of ratings */ + /* translators: %s: Number of ratings. */ sprintf( __( '(%s ratings)' ), '{{ data.num_ratings }}' ), - /* translators: accessibility text */ + /* translators: Accessibility text. */ __( '(opens in a new tab)' ) ); ?> @@ -736,14 +834,147 @@ <# } #> <# if ( data.hasUpdate ) { #> -
-

- {{{ data.update }}} -
+ <# if ( data.updateResponse.compatibleWP && data.updateResponse.compatiblePHP ) { #> +
+

+ {{{ data.update }}} +
+ <# } else { #> +
+

+

+ <# if ( ! data.updateResponse.compatibleWP && ! data.updateResponse.compatiblePHP ) { #> + Please update WordPress, and then learn more about updating PHP.' ), + self_admin_url( 'update-core.php' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } elseif ( current_user_can( 'update_core' ) ) { + printf( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } elseif ( current_user_can( 'update_php' ) ) { + printf( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + ?> + <# } else if ( ! data.updateResponse.compatibleWP ) { #> + Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } + ?> + <# } else if ( ! data.updateResponse.compatiblePHP ) { #> + Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + ?> + <# } #> +

+
+ <# } #> <# } #> <# if ( data.parent ) { #> -

{{{ data.parent }}}' ); ?>

+

+ {{{ data.parent }}}' + ); + ?> +

+ <# } #> + + <# if ( ! data.compatibleWP || ! data.compatiblePHP ) { #> +

+ <# if ( ! data.compatibleWP && ! data.compatiblePHP ) { #> + Please update WordPress, and then learn more about updating PHP.' ), + self_admin_url( 'update-core.php' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } elseif ( current_user_can( 'update_core' ) ) { + printf( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } elseif ( current_user_can( 'update_php' ) ) { + printf( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + ?> + <# } else if ( ! data.compatibleWP ) { #> + Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } + ?> + <# } else if ( ! data.compatiblePHP ) { #> + Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + ?> + <# } #> +

<# } #>

{{{ data.description }}}

@@ -763,10 +994,20 @@ <# } #> - + + <# if ( data.compatibleWP && data.compatiblePHP ) { #> + + <# } else { #> + + <# } #> <# } else { #> - - + <# if ( data.compatibleWP && data.compatiblePHP ) { #> + + + <# } else { #> + + + <# } #> <# } #>