Make WordPress Core


Ignore:
Timestamp:
02/28/2012 09:24:44 PM (13 years ago)
Author:
nacin
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/theme.php

    r20021 r20029  
    66 * @subpackage Theme
    77 */
     8
     9/**
     10 * Returns an array of WP_Theme objects based on the arguments.
     11 *
     12 * Despite advances over get_themes(), this function is still quite expensive, and grows
     13 * linearly with additional themes. Stick to wp_get_theme() if possible.
     14 *
     15 * @since 3.4.0
     16 *
     17 * @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed'
     18 *  (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id'
     19 *  (defaults to current blog; used to find allowed themes; only applies to multisite).
     20 * @return Array of WP_Theme objects.
     21 */
     22function wp_get_themes( $args = array() ) {
     23    global $wp_theme_directories;
     24
     25    $defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
     26    $args = wp_parse_args( $args, $defaults );
     27
     28    static $_themes;
     29    if ( ! isset( $_themes ) ) {
     30        $_themes = array();
     31        $theme_data = search_theme_directories();
     32        // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
     33        // one in the case of a conflict. (Normally, last registered theme root wins.)
     34        $current_theme = get_stylesheet();
     35        $current_theme_root = get_raw_theme_root( $current_theme );
     36        if ( ! in_array( $current_theme_root, $wp_theme_directories ) )
     37            $current_theme_root = WP_CONTENT_DIR . $current_theme_root;
     38        foreach ( (array) $theme_data as $theme_slug => $data ) {
     39            if ( $current_theme == $theme_slug && $current_theme_root != $data['theme_root'] )
     40                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $current_theme_root );
     41            else
     42                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $data['theme_root'] );
     43        }
     44    }
     45
     46    $themes = $_themes;
     47    if ( empty( $themes ) )
     48        return $themes;
     49
     50    if ( null !== $args['errors'] ) {
     51        foreach ( $themes as $theme_slug => $theme ) {
     52            if ( $theme->errors() != $args['errors'] )
     53                unset( $themes[ $theme_slug ] );
     54        }
     55    }
     56
     57    if ( is_multisite() && null !== $args['allowed'] ) {
     58        if ( $allowed = $args['allowed'] ) {
     59            if ( 'network' == $allowed )
     60                $themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_network( $args['blog_id'] ) );
     61            elseif ( 'site' == $allowed )
     62                $themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_site( $args['blog_id'] ) );
     63            else
     64                $themes = array_intersect_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
     65        } else {
     66            $themes = array_diff_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
     67        }
     68    }
     69
     70    return $themes;
     71}
     72
     73/**
     74 * Gets a WP_Theme object for a theme.
     75 *
     76 * @since 3.4.0
     77 *
     78 * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
     79 * @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root()
     80 *  is used to calculate the theme root for the $stylesheet provided (or current theme).
     81 * @return WP_Theme
     82 */
     83function wp_get_theme( $stylesheet = null, $theme_root = null ) {
     84    global $wp_theme_directories;
     85
     86    if ( empty( $stylesheet ) )
     87        $stylesheet = get_stylesheet();
     88
     89    if ( empty( $theme_root ) ) {
     90        $theme_root = get_raw_theme_root( $stylesheet );
     91        if ( ! in_array( $theme_root, $wp_theme_directories ) )
     92            $theme_root = WP_CONTENT_DIR . $theme_root;
     93    }
     94
     95    return new WP_Theme( $stylesheet, $theme_root );
     96}
    897
    998/**
     
    248337
    249338/**
    250  * Retrieve list of themes with theme data in theme directory.
    251  *
    252  * The theme is broken, if it doesn't have a parent theme and is missing either
    253  * style.css and, or index.php. If the theme has a parent theme then it is
    254  * broken, if it is missing style.css; index.php is optional. The broken theme
    255  * list is saved in the {@link $wp_broken_themes} global, which is displayed on
    256  * the theme list in the administration panels.
    257  *
    258  * @since 1.5.0
    259  * @global array $wp_broken_themes Stores the broken themes.
    260  * @global array $wp_themes Stores the working themes.
    261  *
    262  * @return array Theme list with theme data.
    263  */
    264 function get_themes() {
    265     global $wp_themes, $wp_broken_themes;
    266 
    267     if ( isset($wp_themes) )
    268         return $wp_themes;
    269 
    270     if ( !$theme_files = search_theme_directories() )
    271         return false;
    272 
    273     asort( $theme_files );
    274 
    275     $wp_themes = array();
    276 
    277     foreach ( (array) $theme_files as $theme_file ) {
    278         $theme_root = $theme_file['theme_root'];
    279         $theme_file = $theme_file['theme_file'];
    280 
    281         if ( !is_readable("$theme_root/$theme_file") ) {
    282             $wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.'));
    283             continue;
    284         }
    285 
    286         $theme_data = get_theme_data("$theme_root/$theme_file");
    287 
    288         $name        = $theme_data['Name'];
    289         $title       = $theme_data['Title'];
    290         $description = wptexturize($theme_data['Description']);
    291         $version     = $theme_data['Version'];
    292         $author      = $theme_data['Author'];
    293         $template    = $theme_data['Template'];
    294         $stylesheet  = dirname($theme_file);
    295 
    296         $screenshot = false;
    297         foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) {
    298             if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) {
    299                 $screenshot = "screenshot.$ext";
    300                 break;
    301             }
    302         }
    303 
    304         if ( empty($name) ) {
    305             $name = dirname($theme_file);
    306             $title = $name;
    307         }
    308 
    309         $parent_template = $template;
    310 
    311         if ( empty($template) ) {
    312             if ( file_exists("$theme_root/$stylesheet/index.php") )
    313                 $template = $stylesheet;
    314             else
    315                 continue;
    316         }
    317 
    318         $template = trim( $template );
    319 
    320         if ( !file_exists("$theme_root/$template/index.php") ) {
    321             $parent_dir = dirname(dirname($theme_file));
    322             if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) {
    323                 $template = "$parent_dir/$template";
    324                 $template_directory = "$theme_root/$template";
    325             } else {
    326                 /**
    327                  * The parent theme doesn't exist in the current theme's folder or sub folder
    328                  * so lets use the theme root for the parent template.
    329                  */
    330                 if ( isset($theme_files[$template]) && file_exists( $theme_files[$template]['theme_root'] . "/$template/index.php" ) ) {
    331                     $template_directory = $theme_files[$template]['theme_root'] . "/$template";
    332                 } else {
    333                     if ( empty( $parent_template) )
    334                         $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'), 'error' => 'no_template');
    335                     else
    336                         $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 );
    337                     continue;
    338                 }
    339 
    340             }
    341         } else {
    342             $template_directory = trim( $theme_root . '/' . $template );
    343         }
    344 
    345         $stylesheet_files = array();
    346         $template_files = array();
    347 
    348         $stylesheet_dir = @ dir("$theme_root/$stylesheet");
    349         if ( $stylesheet_dir ) {
    350             while ( ($file = $stylesheet_dir->read()) !== false ) {
    351                 if ( !preg_match('|^\.+$|', $file) ) {
    352                     if ( preg_match('|\.css$|', $file) )
    353                         $stylesheet_files[] = "$theme_root/$stylesheet/$file";
    354                     elseif ( preg_match('|\.php$|', $file) )
    355                         $template_files[] = "$theme_root/$stylesheet/$file";
    356                 }
    357             }
    358             @ $stylesheet_dir->close();
    359         }
    360 
    361         $template_dir = @ dir("$template_directory");
    362         if ( $template_dir ) {
    363             while ( ($file = $template_dir->read()) !== false ) {
    364                 if ( preg_match('|^\.+$|', $file) )
    365                     continue;
    366                 if ( preg_match('|\.php$|', $file) ) {
    367                     $template_files[] = "$template_directory/$file";
    368                 } elseif ( is_dir("$template_directory/$file") ) {
    369                     $template_subdir = @ dir("$template_directory/$file");
    370                     if ( !$template_subdir )
    371                         continue;
    372                     while ( ($subfile = $template_subdir->read()) !== false ) {
    373                         if ( preg_match('|^\.+$|', $subfile) )
    374                             continue;
    375                         if ( preg_match('|\.php$|', $subfile) )
    376                             $template_files[] = "$template_directory/$file/$subfile";
    377                     }
    378                     @ $template_subdir->close();
    379                 }
    380             }
    381             @ $template_dir->close();
    382         }
    383 
    384         //Make unique and remove duplicates when stylesheet and template are the same i.e. most themes
    385         $template_files = array_unique($template_files);
    386         $stylesheet_files = array_unique($stylesheet_files);
    387 
    388         $template_dir = $template_directory;
    389         $stylesheet_dir = $theme_root . '/' . $stylesheet;
    390 
    391         if ( empty($template_dir) )
    392             $template_dir = '/';
    393         if ( empty($stylesheet_dir) )
    394             $stylesheet_dir = '/';
    395 
    396         // Check for theme name collision. This occurs if a theme is copied to
    397         // a new theme directory and the theme header is not updated. Whichever
    398         // theme is first keeps the name. Subsequent themes get a suffix applied.
    399         // Default themes themes always trump their pretenders.
    400         if ( isset($wp_themes[$name]) ) {
    401             $trump_cards = array(
    402                 'classic'      => 'WordPress Classic',
    403                 'default'      => 'WordPress Default',
    404                 'twentyten'    => 'Twenty Ten',
    405                 'twentyeleven' => 'Twenty Eleven',
    406                 'twentytwelve' => 'Twenty Twelve',
    407             );
    408             if ( isset( $trump_cards[ $stylesheet ] ) && $name == $trump_cards[ $stylesheet ] ) {
    409                 // If another theme has claimed to be one of our default themes, move
    410                 // them aside.
    411                 $suffix = $wp_themes[$name]['Stylesheet'];
    412                 $new_name = "$name/$suffix";
    413                 $wp_themes[$new_name] = $wp_themes[$name];
    414                 $wp_themes[$new_name]['Name'] = $new_name;
    415             } else {
    416                 $name = "$name/$stylesheet";
    417             }
    418         }
    419 
    420         $wp_themes[$name] = array(
    421             'Name' => $name,
    422             'Title' => $title,
    423             'Description' => $description,
    424             'Author' => $author,
    425             'Author Name' => $theme_data['AuthorName'],
    426             'Author URI' => $theme_data['AuthorURI'],
    427             'Version' => $version,
    428             'Template' => $template,
    429             'Stylesheet' => $stylesheet,
    430             'Template Files' => $template_files,
    431             'Stylesheet Files' => $stylesheet_files,
    432             'Template Dir' => $template_dir,
    433             'Stylesheet Dir' => $stylesheet_dir,
    434             'Status' => $theme_data['Status'],
    435             'Screenshot' => $screenshot,
    436             'Tags' => $theme_data['Tags'],
    437             'Theme Root' => $theme_root,
    438             'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ),
    439         );
    440     }
    441 
    442     unset($theme_files);
    443 
    444     /* Resolve theme dependencies. */
    445     $theme_names = array_keys( $wp_themes );
    446     foreach ( (array) $theme_names as $theme_name ) {
    447         $wp_themes[$theme_name]['Parent Theme'] = '';
    448         if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {
    449             foreach ( (array) $theme_names as $parent_theme_name ) {
    450                 if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {
    451                     $wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];
    452                     break;
    453                 }
    454             }
    455         }
    456     }
    457 
    458     return $wp_themes;
    459 }
    460 
    461 /**
    462339 * Retrieve theme roots.
    463340 *
     
    481358
    482359/**
    483  * Retrieve theme data.
    484  *
    485  * @since 1.5.0
    486  *
    487  * @param string $theme Theme name.
    488  * @return array|null Null, if theme name does not exist. Theme data, if exists.
    489  */
    490 function get_theme($theme) {
    491     $themes = get_themes();
    492 
    493     if ( is_array( $themes ) && array_key_exists( $theme, $themes ) )
    494         return $themes[$theme];
    495 
    496     return null;
    497 }
    498 
    499 /**
    500360 * Retrieve current theme display name.
    501361 *
     
    509369 */
    510370function get_current_theme() {
    511     if ( $theme = get_option('current_theme') )
     371    if ( $theme = get_option( 'current_theme' ) )
    512372        return $theme;
    513373
    514     $themes = get_themes();
    515     $current_theme = 'Twenty Eleven';
    516 
    517     if ( $themes ) {
    518         $theme_names = array_keys( $themes );
    519         $current_template = get_option( 'template' );
    520         $current_stylesheet = get_option( 'stylesheet' );
    521 
    522         foreach ( (array) $theme_names as $theme_name ) {
    523             if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet &&
    524                     $themes[$theme_name]['Template'] == $current_template ) {
    525                 $current_theme = $themes[$theme_name]['Name'];
    526                 break;
    527             }
    528         }
    529     }
    530 
    531     update_option('current_theme', $current_theme);
    532 
    533     return $current_theme;
     374    return wp_get_theme()->get('Name');
    534375}
    535376
Note: See TracChangeset for help on using the changeset viewer.