Updates to WP_Theme, wp_get_themes(), and related deprecated functions, after [UT570] [UT578] [UT579]. see #20103.

* ['Template Files'] and ['Stylesheet Files'] need to return files from the parent theme as well.
 * Don't strip links from the Author header. Some themes rely on the previous behavior, such as to link multiple authors (Sandbox, for example.) Don't restore links to the Name, that's just a bad idea.
 * Ensure we are always passing around arrays in get_files/scandir.
 * Better inline doc for wp_get_themes() arguments.
 * Introduce a 'force' flag for search_theme_directories() to re-scan, rather than return the cache. We will use this to re-build the theme_roots transient in get_theme_roots(), but it is more helpful for unit tests. Since search_theme_directories() is cached, don't cache again in wp_get_themes(). (Again benefits testing.)
 * Handle duplicate theme names in the old get_themes() when two themes match (and neither are a default theme, which is already handled). wp_get_themes() will consider both names to be the same; this is just for back compat since get_themes() is keyed by name.
 * Include an old array key in wp_broken_themes().



git-svn-id: http://svn.automattic.com/wordpress/trunk@20193 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
nacin 2012-03-15 15:39:21 +00:00
parent af84dbcf93
commit 962fae26f4
4 changed files with 43 additions and 33 deletions

View File

@ -917,8 +917,10 @@ function get_broken_themes() {
$themes = wp_get_themes( array( 'errors' => true ) ); $themes = wp_get_themes( array( 'errors' => true ) );
$broken = array(); $broken = array();
foreach ( $themes as $theme ) { foreach ( $themes as $theme ) {
$broken[ $theme->get('Name') ] = array( $name = $theme->get('Name');
'Title' => $theme->get('Name'), $broken[ $name ] = array(
'Name' => $name,
'Title' => $name,
'Description' => $theme->errors()->get_error_message(), 'Description' => $theme->errors()->get_error_message(),
); );
} }

View File

@ -384,12 +384,12 @@ final class WP_Theme implements ArrayAccess {
case 'Stylesheet' : case 'Stylesheet' :
return $this->get_stylesheet(); return $this->get_stylesheet();
case 'Template Files' : case 'Template Files' :
$files = $this->get_files('php'); $files = $this->get_files('php', true);
foreach ( $files as &$file ) foreach ( $files as &$file )
$file = $this->theme_root . '/' . $file; $file = $this->theme_root . '/' . $file;
return $files; return $files;
case 'Stylesheet Files' : case 'Stylesheet Files' :
$files = $this->get_files('css'); $files = $this->get_files('css', true);
foreach ( $files as &$file ) foreach ( $files as &$file )
$file = $this->theme_root . '/' . $file; $file = $this->theme_root . '/' . $file;
return $files; return $files;
@ -555,7 +555,6 @@ final class WP_Theme implements ArrayAccess {
} }
// Fall through otherwise. // Fall through otherwise.
case 'Name' : case 'Name' :
case 'Author' :
static $header_tags = array( static $header_tags = array(
'abbr' => array( 'title' => true ), 'abbr' => array( 'title' => true ),
'acronym' => array( 'title' => true ), 'acronym' => array( 'title' => true ),
@ -565,6 +564,8 @@ final class WP_Theme implements ArrayAccess {
); );
$value = wp_kses( $value, $header_tags ); $value = wp_kses( $value, $header_tags );
break; break;
case 'Author' :
// There shouldn't be anchor tags in Author, but some themes like to be challenging.
case 'Description' : case 'Description' :
static $header_tags_with_a = array( static $header_tags_with_a = array(
'a' => array( 'href' => true, 'title' => true ), 'a' => array( 'href' => true, 'title' => true ),
@ -935,7 +936,9 @@ final class WP_Theme implements ArrayAccess {
if ( $include_parent_files || ! $this->is_child_theme() ) if ( $include_parent_files || ! $this->is_child_theme() )
// Template files can be one level down for the purposes of the theme editor, so this should be $depth = 1. // Template files can be one level down for the purposes of the theme editor, so this should be $depth = 1.
// Todo: We ignore this for now, but this is why the branching is weird. // Todo: We ignore this for now, but this is why the branching is weird.
$files = (array) self::scandir( $this->get_template_directory(), $this->get_template(), array( 'php', 'css' ) ); $files = self::scandir( $this->get_template_directory(), $this->get_template(), array( 'php', 'css' ) );
else
$files = array();
if ( $this->is_child_theme() ) if ( $this->is_child_theme() )
$files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), array( 'php', 'css' ) ) ); $files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), array( 'php', 'css' ) ) );
foreach ( $files as &$group ) foreach ( $files as &$group )
@ -989,14 +992,14 @@ final class WP_Theme implements ArrayAccess {
* @depth int How deep to search for files. Optional, defaults to a flat scan (0 depth). * @depth int How deep to search for files. Optional, defaults to a flat scan (0 depth).
*/ */
private static function scandir( $path, $relative_path, $extensions, $depth = 0 ) { private static function scandir( $path, $relative_path, $extensions, $depth = 0 ) {
if ( is_array( $extensions ) )
$extensions = implode( '|', $extensions );
if ( ! is_dir( $path ) ) if ( ! is_dir( $path ) )
return false; return false;
$results = scandir( $path ); $results = scandir( $path );
$files = array();
$extensions = (array) $extensions;
$files = array_fill_keys( $extensions, array() );
$extensions = implode( '|', $extensions );
foreach ( $results as $result ) { foreach ( $results as $result ) {
if ( '.' == $result || '..' == $result ) if ( '.' == $result || '..' == $result )
@ -1007,9 +1010,6 @@ final class WP_Theme implements ArrayAccess {
$found = self::scandir( $path . '/' . $result, $relative_path . '/' . $result, $extensions, $depth - 1 ); $found = self::scandir( $path . '/' . $result, $relative_path . '/' . $result, $extensions, $depth - 1 );
$files = array_merge_recursive( $files, $found ); $files = array_merge_recursive( $files, $found );
} elseif ( preg_match( '~\.(' . $extensions . ')$~', $result, $match ) ) { } elseif ( preg_match( '~\.(' . $extensions . ')$~', $result, $match ) ) {
if ( ! isset( $files[ $match[1] ] ) )
$files[ $match[1] ] = array( $relative_path . '/'. $result );
else
$files[ $match[1] ][] = $relative_path . '/' . $result; $files[ $match[1] ][] = $relative_path . '/' . $result;
} }
} }

View File

@ -2933,7 +2933,11 @@ function get_themes() {
$wp_themes = array(); $wp_themes = array();
foreach ( $themes as $theme ) { foreach ( $themes as $theme ) {
$wp_themes[ $theme->get('Name') ] = $theme; $name = $theme->get('Name');
if ( isset( $wp_themes[ $name ] ) )
$wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme;
else
$wp_themes[ $name ] = $theme;
} }
return $wp_themes; return $wp_themes;

View File

@ -9,14 +9,19 @@
/** /**
* Returns an array of WP_Theme objects based on the arguments. * Returns an array of WP_Theme objects based on the arguments.
* *
* Despite advances over get_themes(), this function is still quite expensive, and grows * Despite advances over get_themes(), this function is quite expensive, and grows
* linearly with additional themes. Stick to wp_get_theme() if possible. * linearly with additional themes. Stick to wp_get_theme() if possible.
* *
* @since 3.4.0 * @since 3.4.0
* *
* @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed' * @param array $args The search arguments. Optional.
* (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id' * - errors mixed True to return themes with errors, false to return themes without errors, null
* (defaults to current blog; used to find allowed themes; only applies to multisite). * to return all themes. Defaults to false.
* - allowed mixed (Multisite) True to return only allowed themes for a site. False to return only
* disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
* to return only network-allowed themes. Null to return all themes. Defaults to null.
* - blog_id int (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
* synonymous for the current blog.
* @return Array of WP_Theme objects. * @return Array of WP_Theme objects.
*/ */
function wp_get_themes( $args = array() ) { function wp_get_themes( $args = array() ) {
@ -25,25 +30,23 @@ function wp_get_themes( $args = array() ) {
$defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 ); $defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
$args = wp_parse_args( $args, $defaults ); $args = wp_parse_args( $args, $defaults );
static $_theme_directories, $_themes = array(); $theme_directories = search_theme_directories();
if ( ! isset( $_theme_directories ) ) {
$_theme_directories = search_theme_directories();
if ( count( $wp_theme_directories ) > 1 ) { if ( count( $wp_theme_directories ) > 1 ) {
// Make sure the current theme wins out, in case search_theme_directories() picks the wrong // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
// one in the case of a conflict. (Normally, last registered theme root wins.) // one in the case of a conflict. (Normally, last registered theme root wins.)
$current_theme = get_stylesheet(); $current_theme = get_stylesheet();
if ( isset( $theme_directories[ $current_theme ] ) ) {
$root_of_current_theme = get_raw_theme_root( $current_theme ); $root_of_current_theme = get_raw_theme_root( $current_theme );
if ( ! in_array( $root_of_current_theme, $wp_theme_directories ) ) if ( ! in_array( $root_of_current_theme, $wp_theme_directories ) )
$root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme; $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
$_theme_directories[ $current_theme ]['theme_root'] = $root_of_current_theme; $theme_directories[ $current_theme ]['theme_root'] = $root_of_current_theme;
} }
} }
if ( empty( $_theme_directories ) ) if ( empty( $theme_directories ) )
return array(); return array();
$theme_directories = $_theme_directories;
if ( is_multisite() && null !== $args['allowed'] ) { if ( is_multisite() && null !== $args['allowed'] ) {
$allowed = $args['allowed']; $allowed = $args['allowed'];
if ( 'network' === $allowed ) if ( 'network' === $allowed )
@ -355,7 +358,7 @@ function get_theme_roots() {
$theme_roots = get_site_transient( 'theme_roots' ); $theme_roots = get_site_transient( 'theme_roots' );
if ( false === $theme_roots ) { if ( false === $theme_roots ) {
search_theme_directories(); // Regenerate the transient. search_theme_directories( true ); // Regenerate the transient.
$theme_roots = get_site_transient( 'theme_roots' ); $theme_roots = get_site_transient( 'theme_roots' );
} }
return $theme_roots; return $theme_roots;
@ -390,15 +393,16 @@ function register_theme_directory( $directory ) {
* *
* @since 2.9.0 * @since 2.9.0
* *
* @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
* @return array Valid themes found * @return array Valid themes found
*/ */
function search_theme_directories() { function search_theme_directories( $force = false ) {
global $wp_theme_directories; global $wp_theme_directories;
if ( empty( $wp_theme_directories ) ) if ( empty( $wp_theme_directories ) )
return false; return false;
static $found_themes; static $found_themes;
if ( isset( $found_themes ) ) if ( ! $force && isset( $found_themes ) )
return $found_themes; return $found_themes;
$found_themes = array(); $found_themes = array();