Introduce WP_Theme, wp_get_themes(), and wp_get_theme() to replace get_themes(), get_theme(), get_theme_data(), current_theme_info(), and others.

* Getters and Helpers: Introduces a series of methods to allow for easy generation of headers for display, and other theme metadata, including page templates.
 * Screenshots: Handles support for multiple screenshots. (see # Additional screenshots must be PNG and start with screenshot-2.png, and be sequential to be counted. see #19816.
 * Error Handling: Broken themes have a WP_Error object attached to them.
 * Caching: Introduces a wp_cache_themes_persistently filter (also in [20020]) to enable persistent caching of all filesystem and sanitization operations normally handled by WP_Theme (and formerly get_file_data() and get_themes()). Themes are cached individually and across five different cache keys for different data pieces.
 * Compatibility: A WP_Theme object is backwards compatible with a theme's array formerly returned by get_themes() and get_theme(), and an stdClass object formerly returned by current_theme_info().
 * i18n/L10n: Theme headers are now localizable with proper Text Domain and Domain Path headers, like plugins. (Language packs may remove the requirement for headers.) For page templates, see #6007 (not fixed yet, but will be easy now). For headers, fixes #15858.
 * PHP and CSS files: New methods that fetch a list of theme files (for the theme editor) only on demand, rather than only loading them into memory. fixes #11214.

Functions deprecated:
 * get_themes(), get_allowed_themes() and get_broken_themes() -- use wp_get_themes()
 * get_theme() and current_theme_info() -- use wp_get_theme()
 * get_site_allowed_themes() -- use WP_Theme::get_allowed_on_network()
 * wpmu_get_blog_allowedthemes() -- use WP_theme::get_allowed_on_site()

see also [20016], [20018], [20019], [20020], [20021], [20022], [20025], [20026], [20027]. also fixes #19244.

see #20103.



git-svn-id: https://develop.svn.wordpress.org/trunk@20029 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Nacin
2012-02-28 21:24:44 +00:00
parent 233c465de2
commit 53a209a4ee
17 changed files with 1520 additions and 646 deletions

View File

@@ -6,6 +6,95 @@
* @subpackage Theme
*/
/**
* Returns an array of WP_Theme objects based on the arguments.
*
* Despite advances over get_themes(), this function is still quite expensive, and grows
* linearly with additional themes. Stick to wp_get_theme() if possible.
*
* @since 3.4.0
*
* @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed'
* (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id'
* (defaults to current blog; used to find allowed themes; only applies to multisite).
* @return Array of WP_Theme objects.
*/
function wp_get_themes( $args = array() ) {
global $wp_theme_directories;
$defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
$args = wp_parse_args( $args, $defaults );
static $_themes;
if ( ! isset( $_themes ) ) {
$_themes = array();
$theme_data = search_theme_directories();
// 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.)
$current_theme = get_stylesheet();
$current_theme_root = get_raw_theme_root( $current_theme );
if ( ! in_array( $current_theme_root, $wp_theme_directories ) )
$current_theme_root = WP_CONTENT_DIR . $current_theme_root;
foreach ( (array) $theme_data as $theme_slug => $data ) {
if ( $current_theme == $theme_slug && $current_theme_root != $data['theme_root'] )
$_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $current_theme_root );
else
$_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $data['theme_root'] );
}
}
$themes = $_themes;
if ( empty( $themes ) )
return $themes;
if ( null !== $args['errors'] ) {
foreach ( $themes as $theme_slug => $theme ) {
if ( $theme->errors() != $args['errors'] )
unset( $themes[ $theme_slug ] );
}
}
if ( is_multisite() && null !== $args['allowed'] ) {
if ( $allowed = $args['allowed'] ) {
if ( 'network' == $allowed )
$themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_network( $args['blog_id'] ) );
elseif ( 'site' == $allowed )
$themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_site( $args['blog_id'] ) );
else
$themes = array_intersect_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
} else {
$themes = array_diff_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
}
}
return $themes;
}
/**
* Gets a WP_Theme object for a theme.
*
* @since 3.4.0
*
* @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
* @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root()
* is used to calculate the theme root for the $stylesheet provided (or current theme).
* @return WP_Theme
*/
function wp_get_theme( $stylesheet = null, $theme_root = null ) {
global $wp_theme_directories;
if ( empty( $stylesheet ) )
$stylesheet = get_stylesheet();
if ( empty( $theme_root ) ) {
$theme_root = get_raw_theme_root( $stylesheet );
if ( ! in_array( $theme_root, $wp_theme_directories ) )
$theme_root = WP_CONTENT_DIR . $theme_root;
}
return new WP_Theme( $stylesheet, $theme_root );
}
/**
* Whether a child theme is in use.
*
@@ -246,218 +335,6 @@ function get_theme_data( $theme_file ) {
return $theme_data;
}
/**
* Retrieve list of themes with theme data in theme directory.
*
* The theme is broken, if it doesn't have a parent theme and is missing either
* style.css and, or index.php. If the theme has a parent theme then it is
* broken, if it is missing style.css; index.php is optional. The broken theme
* list is saved in the {@link $wp_broken_themes} global, which is displayed on
* the theme list in the administration panels.
*
* @since 1.5.0
* @global array $wp_broken_themes Stores the broken themes.
* @global array $wp_themes Stores the working themes.
*
* @return array Theme list with theme data.
*/
function get_themes() {
global $wp_themes, $wp_broken_themes;
if ( isset($wp_themes) )
return $wp_themes;
if ( !$theme_files = search_theme_directories() )
return false;
asort( $theme_files );
$wp_themes = array();
foreach ( (array) $theme_files as $theme_file ) {
$theme_root = $theme_file['theme_root'];
$theme_file = $theme_file['theme_file'];
if ( !is_readable("$theme_root/$theme_file") ) {
$wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.'));
continue;
}
$theme_data = get_theme_data("$theme_root/$theme_file");
$name = $theme_data['Name'];
$title = $theme_data['Title'];
$description = wptexturize($theme_data['Description']);
$version = $theme_data['Version'];
$author = $theme_data['Author'];
$template = $theme_data['Template'];
$stylesheet = dirname($theme_file);
$screenshot = false;
foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) {
if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) {
$screenshot = "screenshot.$ext";
break;
}
}
if ( empty($name) ) {
$name = dirname($theme_file);
$title = $name;
}
$parent_template = $template;
if ( empty($template) ) {
if ( file_exists("$theme_root/$stylesheet/index.php") )
$template = $stylesheet;
else
continue;
}
$template = trim( $template );
if ( !file_exists("$theme_root/$template/index.php") ) {
$parent_dir = dirname(dirname($theme_file));
if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) {
$template = "$parent_dir/$template";
$template_directory = "$theme_root/$template";
} else {
/**
* The parent theme doesn't exist in the current theme's folder or sub folder
* so lets use the theme root for the parent template.
*/
if ( isset($theme_files[$template]) && file_exists( $theme_files[$template]['theme_root'] . "/$template/index.php" ) ) {
$template_directory = $theme_files[$template]['theme_root'] . "/$template";
} else {
if ( empty( $parent_template) )
$wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'), 'error' => 'no_template');
else
$wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => sprintf( __('The parent theme is missing. Please install the "%s" parent theme.'), $parent_template ), 'error' => 'no_parent', 'parent' => $parent_template );
continue;
}
}
} else {
$template_directory = trim( $theme_root . '/' . $template );
}
$stylesheet_files = array();
$template_files = array();
$stylesheet_dir = @ dir("$theme_root/$stylesheet");
if ( $stylesheet_dir ) {
while ( ($file = $stylesheet_dir->read()) !== false ) {
if ( !preg_match('|^\.+$|', $file) ) {
if ( preg_match('|\.css$|', $file) )
$stylesheet_files[] = "$theme_root/$stylesheet/$file";
elseif ( preg_match('|\.php$|', $file) )
$template_files[] = "$theme_root/$stylesheet/$file";
}
}
@ $stylesheet_dir->close();
}
$template_dir = @ dir("$template_directory");
if ( $template_dir ) {
while ( ($file = $template_dir->read()) !== false ) {
if ( preg_match('|^\.+$|', $file) )
continue;
if ( preg_match('|\.php$|', $file) ) {
$template_files[] = "$template_directory/$file";
} elseif ( is_dir("$template_directory/$file") ) {
$template_subdir = @ dir("$template_directory/$file");
if ( !$template_subdir )
continue;
while ( ($subfile = $template_subdir->read()) !== false ) {
if ( preg_match('|^\.+$|', $subfile) )
continue;
if ( preg_match('|\.php$|', $subfile) )
$template_files[] = "$template_directory/$file/$subfile";
}
@ $template_subdir->close();
}
}
@ $template_dir->close();
}
//Make unique and remove duplicates when stylesheet and template are the same i.e. most themes
$template_files = array_unique($template_files);
$stylesheet_files = array_unique($stylesheet_files);
$template_dir = $template_directory;
$stylesheet_dir = $theme_root . '/' . $stylesheet;
if ( empty($template_dir) )
$template_dir = '/';
if ( empty($stylesheet_dir) )
$stylesheet_dir = '/';
// Check for theme name collision. This occurs if a theme is copied to
// a new theme directory and the theme header is not updated. Whichever
// theme is first keeps the name. Subsequent themes get a suffix applied.
// Default themes themes always trump their pretenders.
if ( isset($wp_themes[$name]) ) {
$trump_cards = array(
'classic' => 'WordPress Classic',
'default' => 'WordPress Default',
'twentyten' => 'Twenty Ten',
'twentyeleven' => 'Twenty Eleven',
'twentytwelve' => 'Twenty Twelve',
);
if ( isset( $trump_cards[ $stylesheet ] ) && $name == $trump_cards[ $stylesheet ] ) {
// If another theme has claimed to be one of our default themes, move
// them aside.
$suffix = $wp_themes[$name]['Stylesheet'];
$new_name = "$name/$suffix";
$wp_themes[$new_name] = $wp_themes[$name];
$wp_themes[$new_name]['Name'] = $new_name;
} else {
$name = "$name/$stylesheet";
}
}
$wp_themes[$name] = array(
'Name' => $name,
'Title' => $title,
'Description' => $description,
'Author' => $author,
'Author Name' => $theme_data['AuthorName'],
'Author URI' => $theme_data['AuthorURI'],
'Version' => $version,
'Template' => $template,
'Stylesheet' => $stylesheet,
'Template Files' => $template_files,
'Stylesheet Files' => $stylesheet_files,
'Template Dir' => $template_dir,
'Stylesheet Dir' => $stylesheet_dir,
'Status' => $theme_data['Status'],
'Screenshot' => $screenshot,
'Tags' => $theme_data['Tags'],
'Theme Root' => $theme_root,
'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ),
);
}
unset($theme_files);
/* Resolve theme dependencies. */
$theme_names = array_keys( $wp_themes );
foreach ( (array) $theme_names as $theme_name ) {
$wp_themes[$theme_name]['Parent Theme'] = '';
if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {
foreach ( (array) $theme_names as $parent_theme_name ) {
if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {
$wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];
break;
}
}
}
}
return $wp_themes;
}
/**
* Retrieve theme roots.
*
@@ -479,23 +356,6 @@ function get_theme_roots() {
return $theme_roots;
}
/**
* Retrieve theme data.
*
* @since 1.5.0
*
* @param string $theme Theme name.
* @return array|null Null, if theme name does not exist. Theme data, if exists.
*/
function get_theme($theme) {
$themes = get_themes();
if ( is_array( $themes ) && array_key_exists( $theme, $themes ) )
return $themes[$theme];
return null;
}
/**
* Retrieve current theme display name.
*
@@ -508,29 +368,10 @@ function get_theme($theme) {
* @return string
*/
function get_current_theme() {
if ( $theme = get_option('current_theme') )
if ( $theme = get_option( 'current_theme' ) )
return $theme;
$themes = get_themes();
$current_theme = 'Twenty Eleven';
if ( $themes ) {
$theme_names = array_keys( $themes );
$current_template = get_option( 'template' );
$current_stylesheet = get_option( 'stylesheet' );
foreach ( (array) $theme_names as $theme_name ) {
if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet &&
$themes[$theme_name]['Template'] == $current_template ) {
$current_theme = $themes[$theme_name]['Name'];
break;
}
}
}
update_option('current_theme', $current_theme);
return $current_theme;
return wp_get_theme()->get('Name');
}
/**