WordPress.org

Make WordPress Core

Ticket #20103: wp_theme.diff

File wp_theme.diff, 98.7 KB (added by nacin, 6 years ago)
  • wp-includes/class-wp-customize.php

     
    8181
    8282                add_filter( 'template', array( $this, 'get_template' ) );
    8383                add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
    84                 add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
    8584
    8685                // @link: http://core.trac.wordpress.org/ticket/20027
    8786                add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
     
    235234        }
    236235
    237236        /**
    238          * Filter the current theme and return the name of the previewed theme.
    239          *
    240          * @since 3.4.0
    241          *
    242          * @return string Theme name.
    243          */
    244         public function current_theme( $current_theme ) {
    245                 $themes = get_themes();
    246 
    247                 if ( ! $themes )
    248                         return $current_theme;
    249 
    250                 foreach ( $themes as $theme ) {
    251                         if ( $theme['Stylesheet'] == $this->stylesheet && $theme['Template'] == $this->template )
    252                                 return $theme['Name'];
    253                 }
    254 
    255                 return $current_theme;
    256         }
    257 
    258         /**
    259237         * Trigger save action and load customize controls.
    260238         *
    261239         * @since 3.4.0
  • wp-includes/update.php

     
    235235        if ( defined( 'WP_INSTALLING' ) )
    236236                return false;
    237237
    238         if ( !function_exists( 'get_themes' ) )
    239                 require_once( ABSPATH . 'wp-includes/theme.php' );
    240 
    241         $installed_themes = get_themes( );
     238        $installed_themes = wp_get_themes();
    242239        $last_update = get_site_transient( 'update_themes' );
    243240        if ( ! is_object($last_update) )
    244241                $last_update = new stdClass;
    245242
    246243        $themes = array();
    247244        $checked = array();
    248         $exclude_fields = array('Template Files', 'Stylesheet Files', 'Status', 'Theme Root', 'Theme Root URI', 'Template Dir', 'Stylesheet Dir', 'Description', 'Tags', 'Screenshot');
    249245
    250246        // Put slug of current theme into request.
    251247        $themes['current_theme'] = get_option( 'stylesheet' );
    252248
    253         foreach ( (array) $installed_themes as $theme_title => $theme ) {
    254                 $themes[$theme['Stylesheet']] = array();
    255                 $checked[$theme['Stylesheet']] = $theme['Version'];
     249        foreach ( $installed_themes as $theme ) {
     250                $checked[ $theme->get_stylesheet() ] = $theme->get('Version');
    256251
    257                 $themes[$theme['Stylesheet']]['Name'] = $theme['Name'];
    258                 $themes[$theme['Stylesheet']]['Version'] = $theme['Version'];
    259 
    260                 foreach ( (array) $theme as $key => $value ) {
    261                         if ( !in_array($key, $exclude_fields) )
    262                                 $themes[$theme['Stylesheet']][$key] = $value;
    263                 }
     252                $themes[ $theme->get_stylesheet() ] = array(
     253                        'Name'       => $theme->get('Name'),
     254                        'Title'      => $theme->get('Name'),
     255                        'Version'    => $theme->get('Version'),
     256                        'Author'     => $theme->get('Author'),
     257                        'Author URI'  => $theme->get('AuthorURI'),
     258                        'Template'   => $theme->get_template(),
     259                        'Stylesheet' => $theme->get_stylesheet(),
     260                );
    264261        }
    265262
    266263        // Check for update on a different schedule, depending on the page.
  • wp-includes/class-wp-theme.php

     
     1<?php
     2/**
     3 * WP_Theme Class
     4 *
     5 * @package WordPress
     6 * @subpackage Theme
     7 */
     8
     9final class WP_Theme implements ArrayAccess {
     10
     11        /**
     12         * Headers for style.css files.
     13         *
     14         * @static
     15         * @access private
     16         * @var array
     17         */
     18        private static $file_headers = array(
     19                'Name'        => 'Theme Name',
     20                'ThemeURI'    => 'Theme URI',
     21                'Description' => 'Description',
     22                'Author'      => 'Author',
     23                'AuthorURI'   => 'Author URI',
     24                'Version'     => 'Version',
     25                'Template'    => 'Template',
     26                'Status'      => 'Status',
     27                'Tags'        => 'Tags',
     28                'TextDomain'  => 'Text Domain',
     29                'DomainPath'  => 'Domain Path',
     30        );
     31
     32        /**
     33         * Absolute path to the theme root, usually wp-content/themes
     34         *
     35         * @access private
     36         * @var string
     37         */
     38        private $theme_root;
     39
     40        /**
     41         * Header data from the theme's style.css file.
     42         *
     43         * @access private
     44         * @var array
     45         */
     46        private $headers = array();
     47
     48        /**
     49         * Header data from the theme's style.css file after being sanitized.
     50         *
     51         * @access private
     52         * @var array
     53         */
     54        private $headers_sanitized;
     55
     56        /**
     57         * Header name from the theme's style.css after being translated.
     58         *
     59         * Cached due to sorting functions running over the translated name.
     60         */
     61        private $name_translated;
     62
     63        /**
     64         * Errors encountered when initializing the theme.
     65         *
     66         * @access private
     67         * @var WP_Error
     68         */
     69        private $errors;
     70
     71        /**
     72         * The directory name of the theme's files, inside the theme root.
     73         *
     74         * In the case of a child theme, this is directory name of the the child theme.
     75         * Otherwise, 'stylesheet' is the same as 'template'.
     76         *
     77         * @access private
     78         * @var string
     79         */
     80        private $stylesheet;
     81
     82        /**
     83         * The directory name of the theme's files, inside the theme root.
     84         *
     85         * In the case of a child theme, this is the directory name of the parent theme.
     86         * Otherwise, 'template' is the same as 'stylesheet'.
     87         *
     88         * @access private
     89         * @var string
     90         */
     91        private $template;
     92
     93        /**
     94         * A reference to the parent theme, in the case of a child theme.
     95         *
     96         * @access private
     97         * @var WP_Theme
     98         */
     99        private $parent;
     100
     101        /**
     102         * Flag for whether the theme's textdomain is loaded.
     103         *
     104         * @access private
     105         * @var bool
     106         */
     107        private $textdomain_loaded;
     108
     109        /**
     110         * Flag for whether the themes cache bucket should be persistently cached.
     111         *
     112         * Default is false. Can be set with the wp_cache_themes_persistent filter.
     113         *
     114         * @access private
     115         * @var bool
     116         */
     117        private static $persistently_cache;
     118
     119        /**
     120         * Expiration time for the themes cache bucket.
     121         *
     122         * By default the bucket is not cached, so this value is useless.
     123         *
     124         * @access private
     125         * @var bool
     126         */
     127        private static $cache_expiration = 7200;
     128
     129        /**
     130         * Constructor for WP_Theme.
     131         *
     132         * @param string $theme_dir Directory of the theme within the theme_root.
     133         * @param string $theme_root Theme root.
     134         * @param WP_Error|null $child If this theme is a parent theme, the child may be passed for validation purposes.
     135         */
     136        public function __construct( $theme_dir, $theme_root, $child = null ) {
     137                // Initialize caching on first run.
     138                if ( ! isset( self::$persistently_cache ) ) {
     139                        self::$persistently_cache = apply_filters( 'wp_cache_themes_persistently', false );
     140                        if ( is_int( self::$persistently_cache ) )
     141                                self::$cache_expiration = self::$persistently_cache;
     142                        elseif ( ! self::$persistently_cache )
     143                                wp_cache_add_non_persistent_groups( 'themes' );
     144                }
     145
     146                $this->theme_root = $theme_root;
     147                $this->stylesheet = $theme_dir;
     148                $theme_file = $this->stylesheet . '/style.css';
     149
     150                $cache = $this->cache_get( 'theme' );
     151
     152                if ( is_array( $cache ) ) {
     153                        foreach ( array( 'errors', 'headers', 'template', 'stylesheet' ) as $key ) {
     154                                if ( isset( $cache[ $key ] ) )
     155                                        $this->$key = $cache[ $key ];
     156                        }
     157                        if ( $this->errors )
     158                                return;
     159                } elseif ( ! file_exists( $this->theme_root . '/' . $theme_file ) ) {
     160                        $this->headers['Name'] = $this->stylesheet;
     161                        $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) );
     162                        $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) );
     163                        if ( ! file_exists( $this->theme_root ) ) // Don't cache this one.
     164                                $this->errors->add( 'theme_root_missing', __( 'ERROR: The themes directory is either empty or doesn&#8217;t exist. Please check your installation.' ) );
     165                        return;
     166                } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) {
     167                        $this->headers['Name'] = $this->stylesheet;
     168                        $this->errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
     169                        $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) );
     170                        return;
     171                } else {
     172                        $this->headers = get_file_data( $this->theme_root . '/' . $theme_file, self::$file_headers, 'theme' );
     173                }
     174
     175                if ( ! $this->template = $this->get('Template') ) {
     176                        if ( file_exists( $this->theme_root . '/' . $this->stylesheet . '/index.php' ) ) {
     177                                $this->template = $this->stylesheet;
     178                        } else {
     179                                $this->errors = new WP_Error( 'theme_no_index', __( 'Template is missing.' ) );
     180                                $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) );
     181                                return;
     182                        }
     183                }
     184
     185                if ( $this->template != $this->stylesheet && ! file_exists( $this->theme_root . '/' . $this->template . '/index.php' ) ) {
     186                        // If we're in a directory of themes inside /themes, look for the parent nearby.
     187                        // wp-content/themes/directory-of-themes/*
     188                        $parent_dir = dirname( $this->stylesheet );
     189                        if ( '.' != $parent_dir && file_exists( $this->theme_root . '/' . $parent_dir . '/' . $this->template . '/index.php' ) ) {
     190                                $this->template = $parent_dir . '/' . $this->template;
     191                        } elseif ( ( $directories = search_theme_directories() ) && isset( $directories[ $this->template ] ) ) {
     192                                // Look for the template in the search_theme_directories() results, in case it is in another theme root.
     193                                // We don't look into directories of themes, just the theme root.
     194                                $theme_root_template = $directories[ $this->template ]['theme_root'];
     195                        } else {
     196                                // Parent theme is missing.
     197                                $this->errors = new WP_Error( 'theme_no_parent', sprintf( __( 'The parent theme is missing. Please install the "%s" parent theme.' ), $this->template ) );
     198                                $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) );
     199                                return;
     200                        }
     201                }
     202
     203                // @TODO Check for theme name collision. But guess what? We don't care anymore! We only care about clashing matches found in search_theme_directories().
     204
     205                // Set the parent, if we're a child theme.
     206                if ( $this->template != $this->stylesheet ) {
     207                        // If we are a parent, then there is a problem. Only two generations allowed! Cancel things out.
     208                        if ( is_a( $child, 'WP_Theme' ) && $child->template == $this->stylesheet ) {
     209                                $child->parent = null;
     210                                $child->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $child->template ) );
     211                                $child->cache_add( 'theme', array( 'headers' => $child->headers, 'errors' => $child->errors, 'stylesheet' => $child->stylesheet, 'template' => $child->template ) );
     212                                // The two themes actually reference each other with the Template header.
     213                                if ( $child->stylesheet == $this->template ) {
     214                                        $this->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $this->template ) );
     215                                        $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) );
     216                                }
     217                                return;
     218                        }
     219                        // Set the parent. Pass the current instance so we can do the crazy checks above and assess errors.
     220                        $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this );
     221                }
     222
     223                // We're good. If we didn't retrieve from cache, set it.
     224                if ( ! is_array( $cache ) )
     225                        $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) );
     226        }
     227
     228        /**
     229         * __isset() magic method for properties formerly returned by current_theme_info()
     230         */
     231        public function __isset( $offset ) {
     232                static $properties = array(
     233                        'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet',
     234                        'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri',
     235                );
     236
     237                return in_array( $offset, $properties );
     238        }
     239
     240        /**
     241         * __get() magic method for properties formerly returned by current_theme_info()
     242         */
     243        public function __get( $offset ) {
     244                switch ( $offset ) {
     245                        case 'name' :
     246                        case 'title' :
     247                                return $this->get('Name');
     248                        case 'version' :
     249                                return $this->get('Version');
     250                        case 'parent_theme' :
     251                                return $this->parent ? $this->parent->get('Name') : '';
     252                        case 'template_dir' :
     253                                return $this->get_template_directory();
     254                        case 'stylesheet_dir' :
     255                                return $this->get_stylesheet_directory();
     256                        case 'template' :
     257                                return $this->get_template();
     258                        case 'stylesheet' :
     259                                return $this->get_stylesheet();
     260                        case 'screenshot' :
     261                                return $this->get_screenshot();
     262                        // 'author' and 'description' did not previously return translated data.
     263                        case 'description' :
     264                                return $this->display('Description');
     265                        case 'author' :
     266                                return $this->display('Author');
     267                        case 'tags' :
     268                                return $this->get( 'Tags' );
     269                        case 'theme_root' :
     270                                return $this->get_theme_root();
     271                        case 'theme_root_uri' :
     272                                return $this->get_theme_root_uri();
     273                }
     274        }
     275
     276        /**
     277         * Method to implement ArrayAccess for keys formerly returned by get_themes()
     278         */
     279    public function offsetSet( $offset, $value ) {}
     280
     281        /**
     282         * Method to implement ArrayAccess for keys formerly returned by get_themes()
     283         */
     284    public function offsetUnset( $offset ) {}
     285
     286        /**
     287         * Method to implement ArrayAccess for keys formerly returned by get_themes()
     288         */
     289    public function offsetExists( $offset ) {
     290        static $keys = array(
     291                'Name', 'Version', 'Status', 'Title', 'Author', 'Author Name', 'Author URI', 'Description',
     292                        'Template', 'Stylesheet', 'Template Files', 'Stylesheet Files', 'Template Dir', 'Stylesheet Dir',
     293                         'Screenshot', 'Tags', 'Theme Root', 'Theme Root URI', 'Parent Theme',
     294                );
     295
     296        return in_array( $offset, $keys );
     297        }
     298
     299        /**
     300         * Method to implement ArrayAccess for keys formerly returned by get_themes()
     301         */
     302        public function offsetGet( $offset ) {
     303        switch ( $offset ) {
     304                        case 'Name' :
     305                        case 'Version' :
     306                        case 'Status' :
     307                                return $this->get( $offset );
     308                        case 'Title' :
     309                                return $this->get('Name');
     310                        // Author, Author Name, Author URI, and Description did not
     311                        // previously return translated data. We are doing so now.
     312                        // Title and Name could have been used as the key for get_themes(),
     313                        // so both to remain untranslated for back compatibility.
     314                        case 'Author' :
     315                                return $this->display( 'Author');
     316                        case 'Author Name' :
     317                                return $this->display( 'Author', false);
     318                        case 'Author URI' :
     319                                return $this->display('AuthorURI');
     320                        case 'Description' :
     321                                return $this->display( 'Description');
     322                        case 'Template' :
     323                                return $this->get_template();
     324                        case 'Stylesheet' :
     325                                return $this->get_stylesheet();
     326                        case 'Template Files' :
     327                                $files = $this->get_files('php');
     328                                foreach ( $files as &$file )
     329                                        $file = $this->theme_root . '/' . $file;
     330                                return $files;
     331                        case 'Stylesheet Files' :
     332                                $files = $this->get_files('css');
     333                                foreach ( $files as &$file )
     334                                        $file = $this->theme_root . '/' . $file;
     335                                return $files;
     336                        case 'Template Dir' :
     337                                return $this->get_template_directory();
     338                        case 'Stylesheet Dir' :
     339                                return $this->get_stylesheet_directory();
     340                        case 'Screenshot' :
     341                                return $this->get_screenshot();
     342                        case 'Tags' :
     343                                return $this->get('Tags');
     344                        case 'Theme Root' :
     345                                return $this->get_theme_root();
     346                        case 'Theme Root URI' :
     347                                return $this->get_theme_root_uri();
     348                        case 'Parent Theme' :
     349                                return $this->parent ? $this->parent->get('Name') : '';
     350                        default :
     351                                return null;
     352                }
     353        }
     354
     355        /**
     356         * Returns errors property.
     357         *
     358         * @since 3.4.0
     359         * @access public
     360         *
     361         * @return WP_Error|bool WP_Error if there are errors, or false.
     362         */
     363        public function errors() {
     364                return is_wp_error( $this->errors ) ? $this->errors : false;
     365        }
     366
     367        /**
     368         * Returns reference to the parent theme.
     369         *
     370         * @since 3.4.0
     371         * @access public
     372         *
     373         * @return WP_Theme|bool Parent theme, or false if the current theme is not a child theme.
     374         */
     375        public function parent() {
     376                return isset( $this->parent ) ? $this->parent : false;
     377        }
     378
     379        /**
     380         * Adds theme data to cache.
     381         *
     382         * Cache entries keyed by the theme and the type of data.
     383         *
     384         * @access private
     385         * @since 3.4.0
     386         *
     387         * @param string $key Type of data to store (theme, screenshot, screenshot_count, files, headers)
     388         * @param string $data Data to store
     389         * @return bool Return value from wp_cache_add()
     390         */
     391        private function cache_add( $key, $data ) {
     392                return wp_cache_add( $key . '-' . $this->theme_root . '/' . $this->stylesheet, $data, 'themes', self::$cache_expiration );
     393        }
     394
     395        /**
     396         * Gets theme data from cache.
     397         *
     398         * Cache entries are keyed by the theme and the type of data.
     399         *
     400         * @access private
     401         * @since 3.4.0
     402         *
     403         * @param string $key Type of data to retrieve (theme, screenshot, screenshot_count, files, headers)
     404         * @return mixed Retrieved data
     405         */
     406        private function cache_get( $key ) {
     407                return wp_cache_get( $key . '-' . $this->theme_root . '/' . $this->stylesheet, 'themes' );
     408        }
     409
     410        /**
     411         * Clears the cache for the theme.
     412         *
     413         * @access public
     414         * @since 3.4.0
     415         */
     416        public function clear_cache() {
     417                wp_cache_delete( 'theme-' . $this->cache_key, 'themes' );
     418                wp_cache_delete( 'screenshot-' . $this->cache_key, 'themes' );
     419                wp_cache_delete( 'screenshot_count-' . $this->cache_key, 'themes' );
     420                wp_cache_delete( 'files-' . $this->cache_key, 'themes' );
     421                wp_cache_delete( 'headers-' . $this->cache_key, 'themes' );
     422        }
     423
     424        /**
     425         * Gets a theme header.
     426         *
     427         * The header is sanitized.
     428         *
     429         * @access public
     430         * @since 3.4.0
     431         *
     432         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
     433         * @return string String on success, false on failure.
     434         */
     435        public function get( $header ) {
     436                if ( ! isset( $this->headers[ $header ] ) )
     437                        return false;
     438
     439                if ( ! isset( $this->headers_sanitized ) ) {
     440                        $this->headers_sanitized = $this->cache_get( 'headers' );
     441                        if ( ! is_array( $this->headers_sanitized ) )
     442                                $headers = array();
     443                }
     444
     445                if ( isset( $this->headers_sanitized[ $header ] ) )
     446                        return $this->headers_sanitized[ $header ];
     447
     448                // If an external object cache does not consider themes to be a persistent group, sanitize everything and cache it.
     449                if ( self::$persistently_cache ) {
     450                        foreach ( array_keys( $this->headers ) as $header )
     451                                $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] );
     452                        $this->cache_add( 'headers', $this->headers_sanitized );
     453                } else {
     454                        $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] );
     455                }
     456
     457                return $this->headers_sanitized[ $header ];
     458        }
     459
     460        /**
     461         * Gets a theme header ready for display (marked up, translated).
     462         *
     463         * @access public
     464         * @since 3.4.0
     465         *
     466         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
     467         * @param bool $markup Optional. Whether to mark up the header. Defaults to true.
     468         * @param bool $translate Optional. Whether to translate the header. Defaults to true.
     469         * @return string Processed header, false on failure.
     470         */
     471        public function display( $header, $markup = true, $translate = true ) {
     472                $value = $this->get( $header );
     473                if ( false === $value || '' === $value )
     474                        return $value;
     475
     476                if ( ! $this->load_textdomain() )
     477                        $translate = false;
     478
     479                if ( $translate )
     480                        $value = $this->translate_header( $header, $value );
     481
     482                if ( $markup )
     483                        $value = $this->markup_header( $header, $value, $translate );
     484
     485                return $value;
     486        }
     487
     488        /**
     489         * Sanitize a theme header.
     490         *
     491         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
     492         * @param string $value Value to sanitize.
     493         */
     494        private function sanitize_header( $header, $value ) {
     495                switch ( $header ) {
     496                        case 'Status' :
     497                                if ( ! $value ) {
     498                                        $value = 'public';
     499                                        break;
     500                                }
     501                                // Fall through otherwise.
     502                        case 'Name' :
     503                        case 'Author' :
     504                                static $header_tags = array(
     505                                        'abbr'    => array( 'title' => true ),
     506                                        'acronym' => array( 'title' => true ),
     507                                        'code'    => true,
     508                                        'em'      => true,
     509                                        'strong'  => true,
     510                                );
     511                                $value = wp_kses( $value, $header_tags );
     512                                break;
     513                        case 'Description' :
     514                                static $header_tags_with_a = array(
     515                                        'a'       => array( 'href' => true, 'title' => true ),
     516                                        'abbr'    => array( 'title' => true ),
     517                                        'acronym' => array( 'title' => true ),
     518                                        'code'    => true,
     519                                        'em'      => true,
     520                                        'strong'  => true,
     521                                );
     522                                $value = wp_kses( $value, $header_tags_with_a );
     523                                break;
     524                        case 'ThemeURI' :
     525                        case 'AuthorURI' :
     526                                $value = esc_url( $value );
     527                                break;
     528                        case 'Tags' :
     529                                $value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) );
     530                                break;
     531                }
     532
     533                return $value;
     534        }
     535
     536        /**
     537         * Mark up a theme header.
     538         *
     539         * @access private
     540         * @since 3.4.0
     541         *
     542         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
     543         * @param string $value Value to mark up.
     544         * @param string $translate Whether the header has been translated.
     545         * @return string Value, marked up.
     546         */
     547        private function markup_header( $header, $value, $translate ) {
     548                switch ( $header ) {
     549                        case 'Description' :
     550                                $value = wptexturize( $value );
     551                                break;
     552                        case 'Author' :
     553                                if ( $this->get('AuthorURI') ) {
     554                                        static $attr = null;
     555                                        if ( ! isset( $attr ) )
     556                                                $attr = esc_attr__( 'Visit author homepage' );
     557                                        $value = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $this->display( 'AuthorURI', true, $translate ), $attr, $value );
     558                                } elseif ( ! $value ) {
     559                                        $value = __( 'Anonymous' );
     560                                }
     561                                break;
     562                        case 'Tags' :
     563                                static $comma = null;
     564                                if ( ! isset( $comma ) ) {
     565                                        /* translators: used between list items, there is a space after the comma */
     566                                        $comma = __( ', ' );
     567                                }
     568                                $value = implode( $comma, $value );
     569                                break;
     570                }
     571
     572                return $value;
     573        }
     574
     575        /**
     576         * Translate a theme header.
     577         *
     578         * @access private
     579         * @since 3.4.0
     580         *
     581         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
     582         * @param string $value Value to translate.
     583         * @return string Translated value.
     584         */
     585        private function translate_header( $header, $value ) {
     586                switch ( $header ) {
     587                        case 'Name' :
     588                                // Cached for sorting reasons.
     589                                if ( isset( $this->name_translated ) )
     590                                        return $this->name_translated;
     591                                $this->name_translated = translate( $value, $this->get('TextDomain' ) );
     592                                return $this->name_translated;
     593                        case 'Tags' :
     594                                if ( empty( $value ) )
     595                                        return $value;
     596
     597                                static $tags_list;
     598                                if ( ! isset( $tags_list ) ) {
     599                                        $tags_list = array();
     600                                        $feature_list = get_theme_feature_list( false ); // No API
     601                                        foreach ( $feature_list as $tags )
     602                                                $tags_list += $tags;
     603                                }
     604
     605                                foreach ( $value as &$tag ) {
     606                                        if ( isset( $tags_list[ $tag ] ) )
     607                                                $tag = $tags_list[ $tag ];
     608                                }
     609
     610                                return $value;
     611                                break;
     612                        default :
     613                                $value = translate( $value, $this->get('TextDomain') );
     614                }
     615                return $value;
     616        }
     617
     618        /**
     619         * The directory name of the theme's "stylesheet" files, inside the theme root.
     620         *
     621         * In the case of a child theme, this is directory name of the the child theme.
     622         * Otherwise, get_stylesheet() is the same as get_template().
     623         *
     624         * @since 3.4.0
     625         * @access public
     626         *
     627         * @return string Stylesheet
     628         */
     629        public function get_stylesheet() {
     630                return $this->stylesheet;
     631        }
     632
     633        /**
     634         * The directory name of the theme's "template" files, inside the theme root.
     635         *
     636         * In the case of a child theme, this is the directory name of the parent theme.
     637         * Otherwise, the get_template() is the same as get_stylesheet().
     638         *
     639         * @since 3.4.0
     640         * @access public
     641         *
     642         * @return string Template
     643         */
     644        public function get_template() {
     645                return $this->template;
     646        }
     647
     648        /**
     649         * Whether a theme is a child theme.
     650         *
     651         * @since 3.4.0
     652         * @access public
     653         *
     654         * @return bool True if a theme is a child theme, false otherwise.
     655         */
     656        public function is_child_theme() {
     657                return $this->template !== $this->stylesheet;
     658        }
     659
     660        /**
     661         * Returns the absolute path to the directory of a theme's "stylesheet" files.
     662         *
     663         * In the case of a child theme, this is the absolute path to the directory
     664         * of the child theme's files.
     665         *
     666         * @since 3.4.0
     667         * @access public
     668         *
     669         * @return string Absolute path of the stylesheet directory.
     670         */
     671        public function get_stylesheet_directory() {
     672                if ( $this->errors && in_array( 'theme_root_missing', $this->errors->get_error_codes() ) )
     673                        return '';
     674
     675                return $this->theme_root . '/' . $this->stylesheet;
     676        }
     677
     678        /**
     679         * Returns the absolute path to the directory of a theme's "template" files.
     680         *
     681         * In the case of a child theme, this is the absolute path to the directory
     682         * of the parent theme's files.
     683         *
     684         * @since 3.4.0
     685         * @access public
     686         *
     687         * @return string Absolute path of the template directory.
     688         */
     689        public function get_template_directory() {
     690                if ( $this->parent )
     691                        $theme_root = $this->parent->theme_root;
     692                else
     693                        $theme_root = $this->theme_root;
     694
     695                return $theme_root . '/' . $this->template;
     696        }
     697
     698        /**
     699         * Returns the URL to the directory of a theme's "stylesheet" files.
     700         *
     701         * In the case of a child theme, this is the URL to the directory of the
     702         * child theme's files.
     703         *
     704         * @since 3.4.0
     705         * @access public
     706         *
     707         * @return string URL to the stylesheet directory.
     708         */
     709        public function get_stylesheet_directory_uri() {
     710                return $this->theme_root_uri . '/' . $this->stylesheet;
     711        }
     712
     713        /**
     714         * Returns the URL to the directory of a theme's "template" files.
     715         *
     716         * In the case of a child theme, this is the URL to the directory of the
     717         * parent theme's files.
     718         *
     719         * @since 3.4.0
     720         * @access public
     721         *
     722         * @return string URL to the template directory.
     723         */
     724        public function get_template_directory_uri() {
     725                if ( $this->parent )
     726                        $theme_root_uri = $this->parent->theme_root_uri;
     727                else
     728                        $theme_root_uri = $this->theme_root;
     729
     730                return $theme_root . '/' . $this->template;
     731        }
     732
     733        /**
     734         * The absolute path to the directory of the theme root.
     735         *
     736         * This is typically the absolute path to wp-content/themes.
     737         *
     738         * @since 3.4.0
     739         * @access public
     740         *
     741         * @return string Theme root.
     742         */
     743        public function get_theme_root() {
     744                return $this->theme_root;
     745        }
     746
     747        /**
     748         * Returns the URL to the directory of the theme root.
     749         *
     750         * This is typically the absolute path to wp-content/themes.
     751         *
     752         * @since 3.4.0
     753         * @access public
     754         *
     755         * @return string Theme root URI.
     756         */
     757        public function get_theme_root_uri() {
     758                return str_replace( WP_CONTENT_DIR, content_url(), $this->theme_root );
     759        }
     760
     761        /**
     762         * Returns the main screenshot file for the theme.
     763         *
     764         * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed.
     765         *
     766         * Screenshots for a theme must be in the stylesheet directory. (In the case of a child
     767         * theme, a parent theme's screenshots are inherited.)
     768         *
     769         * @since 3.4.0
     770         * @access public
     771         *
     772         * @param string $uri Type of URL to include, either relative or absolute. Defaults to relative.
     773         * @return mixed Screenshot file. False if the theme does not have a screenshot.
     774         */
     775        public function get_screenshot( $uri = 'relative' ) {
     776                $screenshot = $this->cache_get( 'screenshot' );
     777                if ( $screenshot ) {
     778                        if ( 'absolute' == $uri )
     779                                return $this->get_stylesheet_directory_uri() . '/' . $screenshot;
     780                        return $screenshot;
     781                } elseif ( 0 === $screenshot ) {
     782                        return false;
     783                }
     784
     785                foreach ( array( 'png', 'gif', 'jpg', 'jpeg' ) as $ext ) {
     786                        if ( file_exists( $this->get_stylesheet_directory() . "/screenshot.$ext" ) ) {
     787                                $this->cache_add( 'screenshot', 'screenshot.' . $ext );
     788                                if ( 'absolute' == $uri )
     789                                        return $this->get_stylesheet_directory_uri() . '/' . 'screenshot.' . $ext;
     790                                return 'screenshot.' . $ext;
     791                        }
     792                }
     793
     794                $this->cache_add( 'screenshot', 0 );
     795                $this->cache_add( 'screenshot_count', 0 );
     796                return false;
     797        }
     798
     799        /**
     800         * Returns the number of screenshots for a theme.
     801         *
     802         * The first screenshot may be called screenshot.png, .gif, or .jpg. Subsequent
     803         * screenshots can be screenshot-2.png, screenshot-3.png, etc. The count must
     804         * be consecutive for screenshots to be counted, and all screenshots beyond the
     805         * initial one must be image/png files.
     806         *
     807         * @see WP_Theme::get_screenshot()
     808         * @since 3.4.0
     809         * @access public
     810         *
     811         * @return int Number of screenshots. Can be 0.
     812         */
     813        public function get_screenshot_count() {
     814                $screenshot_count = $this->cache_get( 'screenshot_count' );
     815                if ( is_numeric( $screenshot_count ) )
     816                        return $screenshot_count;
     817
     818                // This will set the screenshot cache.
     819                // If there is no screenshot, the screenshot_count cache will also be set.
     820                if ( ! $screenshot = $this->get_screenshot() )
     821                        return 0;
     822
     823                $prefix = $this->get_stylesheet() . '/screenshot-';
     824                $files = self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), 'png', 0 );
     825
     826                $screenshot_count = 1;
     827                while ( in_array( $prefix . ( $screenshot_count + 1 ) . '.png', $files['png'] ) )
     828                        $screenshot_count++;
     829
     830                $this->cache_add( 'screenshot_count', $screenshot_count );
     831                return $screenshot_count;
     832        }
     833
     834        /**
     835         * Returns an array of screenshot filenames.
     836         *
     837         * @see WP_Theme::get_screenshot()
     838         * @see WP_Theme::get_screenshot_count()
     839         * @since 3.4.0
     840         * @access public
     841         *
     842         * @return array Screenshots.
     843         */
     844        public function get_screenshots() {
     845                if ( ! $count = $this->get_screenshot_count() )
     846                        return array();
     847
     848                $screenshots = array( $this->get_screenshot() );
     849                for ( $i = 2; $i <= $count; $i++ )
     850                        $screenshots[] = 'screenshot-' . $i . '.png';
     851                return $screenshots;
     852        }
     853
     854        /**
     855         * Return files in the template and stylesheet directories.
     856         *
     857         * @since 3.4.0
     858         * @access public
     859         *
     860         * @param string|null $type Optional. Type of files to return, either 'php' or 'css'. Defaults to null, for both.
     861         * @return array If a specific $type is requested, returns an array of PHP files. If no $type is requested,
     862         *      returns an array, with the keys being the file types, and the values being an array of files for those type.
     863         */
     864        public function get_files( $type = null, $include_parent_files = false ) {
     865                $files = $this->cache_get( 'files' );
     866                if ( ! is_array( $files ) ) {
     867                        if ( $include_parent_files || ! $this->is_child_theme() )
     868                                // Template files can be one level down for the purposes of the theme editor, so this should be $depth = 1.
     869                                // Todo: We ignore this for now, but this is why the branching is weird.
     870                                $files = (array) self::scandir( $this->get_template_directory(), $this->get_template(), array( 'php', 'css' ) );
     871                        if ( $this->is_child_theme() )
     872                                $files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), array( 'php', 'css' ) ) );
     873                        foreach ( $files as &$group )
     874                                sort( $group );
     875                        $this->cache_add( 'files', $files );
     876                }
     877
     878                if ( null === $type )
     879                        return $files;
     880                elseif ( isset( $files[ $type ] ) )
     881                        return $files[ $type ];
     882
     883                return array();
     884        }
     885
     886        public function get_page_templates() {
     887                // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide.
     888                if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) )
     889                        return array();
     890
     891                $page_templates = $this->cache_get( 'page_templates' );
     892                if ( is_array( $page_templates ) )
     893                        return $page_templates;
     894                $page_templates = array();
     895
     896                $files = (array) self::scandir( $this->get_template_directory(), $this->get_template_directory(), 'php' );
     897                if ( $this->is_child_theme() )
     898                        $files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet_directory(), 'php' ) );
     899
     900                foreach ( $files['php'] as $file ) {
     901                        $headers = get_file_data( $file, array( 'Name' => 'Template Name' ) );
     902                        if ( empty( $headers['Name'] ) )
     903                                continue;
     904                        $page_templates[ $headers['Name'] ] = basename( $file );
     905                }
     906
     907                $this->cache_add( 'page_templates', $page_templates );
     908                return $page_templates;
     909        }
     910
     911        /**
     912         * Scans a directory for files of a certain extension.
     913         *
     914         * @since 3.4.0
     915         * @access public
     916         *
     917         * @param string $path Absolute path to search.
     918         * @param string $relative_path The basename of the absolute path. Used to control the returned path
     919         *      for the found files, particularly when this function recurses to lower depths.
     920         * @param array|string $extensions Array of extensions to find, or string of a single extension.
     921         * @depth int How deep to search for files. Optional, defaults to a flat scan (0 depth).
     922         */
     923        private static function scandir( $path, $relative_path, $extensions, $depth = 0 ) {
     924                if ( is_array( $extensions ) )
     925                        $extensions = implode( '|', $extensions );
     926
     927                if ( ! is_dir( $path ) )
     928                        return false;
     929
     930                $results = scandir( $path );
     931                $files = array();
     932
     933                foreach ( $results as $result ) {
     934                        if ( '.' == $result || '..' == $result )
     935                                continue;
     936                        if ( is_dir( $path . '/' . $result ) ) {
     937                                if ( ! $depth )
     938                                        continue;
     939                                $found = self::scandir( $path . '/' . $result, $relative_path . '/' . $result, $extensions, $depth - 1 );
     940                                $files = array_merge_recursive( $files, $found );
     941                        } elseif ( preg_match( '~\.(' . $extensions . ')$~', $result, $match ) ) {
     942                                if ( ! isset( $files[ $match[1] ] ) )
     943                                        $files[ $match[1] ] = array( $relative_path . '/'. $result );
     944                                else
     945                                        $files[ $match[1] ][] = $relative_path . '/' . $result;
     946                        }
     947                }
     948                return $files;
     949        }
     950
     951        /**
     952         * Loads the theme's textdomain.
     953         *
     954         * Translation files are not inherited from the parent theme. Todo: if this fails for the
     955         * child theme, it should probably try to load the parent theme's translations.
     956         *
     957         * @since 3.4.0
     958         * @access public
     959         *
     960         * @return True if the textdomain was successfully loaded or has already been loaded. False if
     961         *      no textdomain was specified in the file headers, or if the domain could not be loaded.
     962         */
     963        public function load_textdomain() {
     964                if ( isset( $this->textdomain_loaded ) )
     965                        return $this->textdomain_loaded;
     966
     967                $textdomain = $this->get('TextDomain');
     968                if ( ! $textdomain ) {
     969                        $this->textdomain_loaded = false;
     970                        return false;
     971                }
     972
     973                if ( is_textdomain_loaded( $textdomain ) ) {
     974                        $this->textdomain_loaded = true;
     975                        return true;
     976                }
     977
     978                $path = $this->get_stylesheet_directory();
     979                if ( $domainpath = $this->get('DomainPath') )
     980                        $path .= $domainpath;
     981
     982                $this->textdomain_loaded = load_theme_textdomain( $textdomain, $path );
     983                return $this->textdomain_loaded;
     984        }
     985
     986        /**
     987         * Whether the theme is allowed (multisite only).
     988         *
     989         * @since 3.4.0
     990         * @access public
     991         *
     992         * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site'
     993         *      settings, or 'both'. Defaults to 'both'.
     994         * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current blog.
     995         * @return bool Whether the theme is allowed for the network. Returns true in single-site.
     996         */
     997        public function is_allowed( $check = 'both', $blog_id = null ) {
     998                if ( ! is_multisite() )
     999                        return true;
     1000
     1001                if ( 'both' == $check || 'network' == $check ) {
     1002                        $allowed = self::get_allowed_on_network();
     1003                        if ( ! empty( $allowed[ $this->get_stylesheet() ] ) )
     1004                                return true;
     1005                }
     1006
     1007                if ( 'both' == $check || 'site' == $check ) {
     1008                        $allowed = self::get_allowed_on_site( $blog_id );
     1009                        if ( ! empty( $allowed[ $this->get_stylesheet() ] ) )
     1010                                return true;
     1011                }
     1012
     1013                return false;
     1014        }
     1015
     1016        /**
     1017         * Returns array of stylesheet names of themes allowed on the site or network.
     1018         *
     1019         * @since 3.4.0
     1020         * @access public
     1021         *
     1022         * @param int $blog_id Optional. Defaults to current blog.
     1023         * @return array Array of stylesheet names.
     1024         */
     1025        public static function get_allowed( $blog_id = null ) {
     1026                return array_merge( self::get_allowed_on_network(), self::get_allowed_on_site( $blog_id ) );
     1027        }
     1028
     1029        /**
     1030         * Returns array of stylesheet names of themes allowed on the network.
     1031         *
     1032         * @since 3.4.0
     1033         * @access public
     1034         *
     1035         * @return array Array of stylesheet names.
     1036         */
     1037        public static function get_allowed_on_network() {
     1038                static $allowed_themes;
     1039                if ( ! isset( $allowed_themes ) )
     1040                        $allowed_themes = (array) get_site_option( 'allowedthemes' );
     1041                return $allowed_themes;
     1042        }
     1043
     1044        /**
     1045         * Returns array of stylesheet names of themes allowed on the site.
     1046         *
     1047         * @since 3.4.0
     1048         * @access public
     1049         *
     1050         * @param int $blog_id Optional. Defaults to current blog.
     1051         * @return array Array of stylesheet names.
     1052         */
     1053        public static function get_allowed_on_site( $blog_id = null ) {
     1054                static $allowed_themes = array();
     1055                if ( ! $blog_id )
     1056                        $blog_id = get_current_blog_id();
     1057
     1058                if ( ! isset( $allowed_themes[ $blog_id ] ) ) {
     1059                        if ( $blog_id == get_current_blog_id() )
     1060                                $allowed_themes[ $blog_id ] = (array) get_option( 'allowedthemes' );
     1061                        else
     1062                                $allowed_themes[ $blog_id ] = (array) get_blog_option( $blog_id, 'allowedthemes' );
     1063                }
     1064
     1065                return $allowed_themes[ $blog_id ];
     1066        }
     1067
     1068        /**
     1069         * Sort themes by name.
     1070         */
     1071        public static function sort_by_name( &$themes ) {
     1072                if ( 0 === strpos( get_locale(), 'en_' ) ) {
     1073                        uasort( $themes, array( 'WP_Theme', '_name_sort' ) );
     1074                } else {
     1075                        uasort( $themes, array( 'WP_Theme', '_name_sort_i18n' ) );
     1076                }
     1077        }
     1078
     1079        /**
     1080         * Callback function for usort() to naturally sort themes by name.
     1081         *
     1082         * Accesses the Name header directly from the class for maximum speed.
     1083         * Would choke on HTML but we don't care enough to slow it down with strip_tags().
     1084         *
     1085         * @since 3.4.0
     1086         * @access public
     1087         */
     1088        private static function _name_sort( $a, $b ) {
     1089                return strnatcasecmp( $a->headers['Name'], $b->headers['Name'] );
     1090        }
     1091
     1092        /**
     1093         * Name sort (with translation).
     1094         *
     1095         * @since 3.4.0
     1096         * @access public
     1097         */
     1098        private static function _name_sort_i18n( $a, $b ) {
     1099                // Don't mark up; Do translate.
     1100                return strnatcasecmp( $a->display( 'Name', false, true ), $b->display( 'Name', false, true ) );
     1101        }
     1102}
     1103
     1104/**
     1105 * Returns an array of WP_Theme objects based on the arguments.
     1106 *
     1107 * Despite advances over get_themes(), this function is still quite expensive, and grows
     1108 * linearly with additional themes. Stick to wp_get_theme() if possible.
     1109 *
     1110 * @since 3.4.0
     1111 *
     1112 * @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed'
     1113 *      (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id'
     1114 *      (defaults to current blog; used to find allowed themes; only applies to multisite).
     1115 * @return Array of WP_Theme objects.
     1116 */
     1117function wp_get_themes( $args = array() ) {
     1118        $defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
     1119        $args = wp_parse_args( $args, $defaults );
     1120
     1121        static $_themes;
     1122        if ( ! isset( $_themes ) ) {
     1123                $theme_data = search_theme_directories();
     1124                // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
     1125                // one in the case of a conflict. (Normally, last registered theme root wins.)
     1126                $current_theme = get_stylesheet();
     1127                $current_theme_root = WP_CONTENT_DIR . get_raw_theme_root( $current_theme );
     1128                foreach ( $theme_data as $theme_slug => $data ) {
     1129                        if ( $current_theme == $theme_slug && $current_theme_root != $data['theme_root'] )
     1130                                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $current_theme_root );
     1131                        else
     1132                                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $data['theme_root'] );
     1133                }
     1134        }
     1135
     1136        $themes = $_themes;
     1137
     1138        if ( null !== $args['errors'] ) {
     1139                foreach ( $themes as $theme_slug => $theme ) {
     1140                        if ( $theme->errors() != $args['errors'] )
     1141                                unset( $themes[ $theme_slug ] );
     1142                }
     1143        }
     1144
     1145        if ( is_multisite() && null !== $args['allowed'] ) {
     1146                if ( $allowed = $args['allowed'] ) {
     1147                        $allowed = 'network' == $allowed || 'site' == $allowed ? $allowed : 'both';
     1148                        $themes = array_intersect_key( $themes, WP_Theme::get_allowed( $allowed, $args['blog_id'] ) );
     1149                } else {
     1150                        $themes = array_diff_key( $themes, WP_Theme::get_allowed( 'both', $args['blog_id'] ) );
     1151                }
     1152        }
     1153
     1154        return $themes;
     1155}
     1156
     1157/**
     1158 * Gets a WP_Theme object for a theme.
     1159 *
     1160 * @since 3.4.0
     1161 *
     1162 * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
     1163 * @param string $theme_root Theme root to look in. Optional. If not specified, get_raw_theme_root()
     1164 *      is used for the $stylesheet provided (or current theme).
     1165 * @return WP_Theme
     1166 */
     1167function wp_get_theme( $stylesheet = null, $theme_root = null ) {
     1168        if ( empty( $stylesheet ) )
     1169                $stylesheet = get_stylesheet();
     1170
     1171        if ( empty( $theme_root ) )
     1172                $theme_root = WP_CONTENT_DIR . get_raw_theme_root( $stylesheet );
     1173
     1174        return new WP_Theme( $stylesheet, $theme_root );
     1175}
     1176 No newline at end of file
  • wp-includes/theme.php

     
    247247}
    248248
    249249/**
    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                 $theme_roots[$stylesheet] = str_replace( WP_CONTENT_DIR, '', $theme_root );
    421                 $wp_themes[$name] = array(
    422                         'Name' => $name,
    423                         'Title' => $title,
    424                         'Description' => $description,
    425                         'Author' => $author,
    426                         'Author Name' => $theme_data['AuthorName'],
    427                         'Author URI' => $theme_data['AuthorURI'],
    428                         'Version' => $version,
    429                         'Template' => $template,
    430                         'Stylesheet' => $stylesheet,
    431                         'Template Files' => $template_files,
    432                         'Stylesheet Files' => $stylesheet_files,
    433                         'Template Dir' => $template_dir,
    434                         'Stylesheet Dir' => $stylesheet_dir,
    435                         'Status' => $theme_data['Status'],
    436                         'Screenshot' => $screenshot,
    437                         'Tags' => $theme_data['Tags'],
    438                         'Theme Root' => $theme_root,
    439                         'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ),
    440                 );
    441         }
    442 
    443         unset($theme_files);
    444 
    445         /* Store theme roots in the DB */
    446         if ( get_site_transient( 'theme_roots' ) != $theme_roots )
    447                 set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours
    448         unset($theme_roots);
    449 
    450         /* Resolve theme dependencies. */
    451         $theme_names = array_keys( $wp_themes );
    452         foreach ( (array) $theme_names as $theme_name ) {
    453                 $wp_themes[$theme_name]['Parent Theme'] = '';
    454                 if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {
    455                         foreach ( (array) $theme_names as $parent_theme_name ) {
    456                                 if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {
    457                                         $wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];
    458                                         break;
    459                                 }
    460                         }
    461                 }
    462         }
    463 
    464         return $wp_themes;
    465 }
    466 
    467 /**
    468250 * Retrieve theme roots.
    469251 *
    470252 * @since 2.9.0
     
    479261
    480262        $theme_roots = get_site_transient( 'theme_roots' );
    481263        if ( false === $theme_roots ) {
    482                 get_themes();
    483                 $theme_roots = get_site_transient( 'theme_roots' ); // this is set in get_theme()
     264                search_theme_directories(); // Regenerated the transient.
     265                $theme_roots = get_site_transient( 'theme_roots' );
    484266        }
    485267        return $theme_roots;
    486268}
    487269
    488270/**
    489  * Retrieve theme data.
    490  *
    491  * @since 1.5.0
    492  *
    493  * @param string $theme Theme name.
    494  * @return array|null Null, if theme name does not exist. Theme data, if exists.
    495  */
    496 function get_theme($theme) {
    497         $themes = get_themes();
    498 
    499         if ( is_array( $themes ) && array_key_exists( $theme, $themes ) )
    500                 return $themes[$theme];
    501 
    502         return null;
    503 }
    504 
    505 /**
    506271 * Retrieve current theme display name.
    507272 *
    508  * If the 'current_theme' option has already been set, then it will be returned
    509  * instead. If it is not set, then each theme will be iterated over until both
    510  * the current stylesheet and current template name.
    511  *
    512273 * @since 1.5.0
    513274 *
    514275 * @return string
    515276 */
    516277function get_current_theme() {
    517         if ( $theme = get_option('current_theme') )
    518                 return $theme;
    519 
    520         $themes = get_themes();
    521         $current_theme = 'Twenty Eleven';
    522 
    523         if ( $themes ) {
    524                 $theme_names = array_keys( $themes );
    525                 $current_template = get_option( 'template' );
    526                 $current_stylesheet = get_option( 'stylesheet' );
    527 
    528                 foreach ( (array) $theme_names as $theme_name ) {
    529                         if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet &&
    530                                         $themes[$theme_name]['Template'] == $current_template ) {
    531                                 $current_theme = $themes[$theme_name]['Name'];
    532                                 break;
    533                         }
    534                 }
    535         }
    536 
    537         update_option('current_theme', $current_theme);
    538 
    539         return $current_theme;
     278        $theme = wp_get_theme();
     279        return $theme->get('Name');
    540280}
    541281
    542282/**
     
    574314 * @return array Valid themes found
    575315 */
    576316function search_theme_directories() {
    577         global $wp_theme_directories, $wp_broken_themes;
     317        global $wp_theme_directories;
    578318        if ( empty( $wp_theme_directories ) )
    579319                return false;
    580320
    581         $theme_files = array();
    582         $wp_broken_themes = array();
     321        static $found_themes;
     322        if ( isset( $found_themes ) )
     323                return $found_themes;
     324        $found_themes = array();
    583325
     326        if ( apply_filters( 'wp_cache_themes_persistently', false ) ) {
     327                $cached_roots = get_site_transient( 'theme_roots' );
     328                if ( is_array( $cached_roots ) ) {
     329                        foreach ( $cached_roots as $theme_dir => $theme_root ) {
     330                                $found_themes[ $theme_dir ] = array(
     331                                        'theme_file' => $theme_dir . '/style.css',
     332                                        'theme_root' => $theme_root,
     333                                );
     334                        }
     335                        return $found_themes;
     336                }
     337        }
     338
    584339        /* Loop the registered theme directories and extract all themes */
    585340        foreach ( (array) $wp_theme_directories as $theme_root ) {
    586341                $theme_loc = $theme_root;
    587342
    588343                /* We don't want to replace all forward slashes, see Trac #4541 */
    589344                if ( '/' != WP_CONTENT_DIR )
    590                         $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root);
     345                        $theme_loc = str_replace( WP_CONTENT_DIR, '', $theme_root );
    591346
    592347                /* Files in the root of the current theme directory and one subdir down */
    593                 $themes_dir = @ opendir($theme_root);
    594 
    595                 if ( !$themes_dir )
     348                $dirs = @ scandir( $theme_root );
     349                if ( ! $dirs )
    596350                        return false;
    597 
    598                 while ( ($theme_dir = readdir($themes_dir)) !== false ) {
    599                         if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) {
    600                                 if ( $theme_dir[0] == '.' || $theme_dir == 'CVS' )
    601                                         continue;
    602 
    603                                 $stylish_dir = @opendir($theme_root . '/' . $theme_dir);
    604                                 $found_stylesheet = false;
    605 
    606                                 while ( ($theme_file = readdir($stylish_dir)) !== false ) {
    607                                         if ( $theme_file == 'style.css' ) {
    608                                                 $theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root );
    609                                                 $found_stylesheet = true;
    610                                                 break;
    611                                         }
     351                foreach ( $dirs as $dir ) {
     352                        if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' )
     353                                continue;
     354                        if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) {
     355                                // wp-content/themes/a-single-theme
     356                                // wp-content/themes is $theme_root, a-single-theme is $dir
     357                                $found_themes[ $dir ] = array(
     358                                        'theme_file' => $dir . '/style.css',
     359                                        'theme_root' => $theme_root,
     360                                );
     361                        } else {
     362                                $found_theme = false;
     363                                // wp-content/themes/a-folder-of-themes/*
     364                                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
     365                                $sub_dirs = @ scandir( $theme_root . '/' . $dir );
     366                                if ( ! $sub_dirs )
     367                                        return false;
     368                                foreach ( $sub_dirs as $sub_dir ) {
     369                                        if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' )
     370                                                continue;
     371                                        if ( ! file_exists( $theme_root . '/' . $dir . '/' . $sub_dir . '/style.css' ) )
     372                                                continue;
     373                                        $found_themes[ $dir . '/' . $sub_dir ] = array(
     374                                                'theme_file' => $dir . '/' . $sub_dir . '/style.css',
     375                                                'theme_root' => $theme_root,
     376                                        );
     377                                        $found_theme = true;
    612378                                }
    613                                 @closedir($stylish_dir);
     379                                // Never mind the above, it's just a theme missing a style.css.
     380                                // Return it; WP_Theme will catch the error.
     381                                if ( ! $found_theme )
     382                                        $found_themes[ $dir ] = array(
     383                                                'theme_file' => $dir . '/style.css',
     384                                                'theme_root' => $theme_root,
     385                                        );
     386                        }
     387                }
     388        }
    614389
    615                                 if ( !$found_stylesheet ) { // look for themes in that dir
    616                                         $subdir = "$theme_root/$theme_dir";
    617                                         $subdir_name = $theme_dir;
    618                                         $theme_subdirs = @opendir( $subdir );
     390        asort( $found_themes );
    619391
    620                                         $found_subdir_themes = false;
    621                                         while ( ($theme_subdir = readdir($theme_subdirs)) !== false ) {
    622                                                 if ( is_dir( $subdir . '/' . $theme_subdir) && is_readable($subdir . '/' . $theme_subdir) ) {
    623                                                         if ( $theme_subdir[0] == '.' || $theme_subdir == 'CVS' )
    624                                                                 continue;
     392        $theme_roots = array();
     393        foreach ( $found_themes as $theme_dir => $theme_data ) {
     394                $theme_roots[ $theme_dir ] = $theme_data['theme_root'];
     395        }
    625396
    626                                                         $stylish_dir = @opendir($subdir . '/' . $theme_subdir);
    627                                                         $found_stylesheet = false;
     397        if ( $theme_roots != get_site_transient( 'theme_roots' ) )
     398                set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours
    628399
    629                                                         while ( ($theme_file = readdir($stylish_dir)) !== false ) {
    630                                                                 if ( $theme_file == 'style.css' ) {
    631                                                                         $theme_files["$theme_dir/$theme_subdir"] = array( 'theme_file' => $subdir_name . '/' . $theme_subdir . '/' . $theme_file, 'theme_root' => $theme_root );
    632                                                                         $found_stylesheet = true;
    633                                                                         $found_subdir_themes = true;
    634                                                                         break;
    635                                                                 }
    636                                                         }
    637                                                         @closedir($stylish_dir);
    638                                                 }
    639                                         }
    640                                         @closedir($theme_subdirs);
    641                                         if ( !$found_subdir_themes )
    642                                                 $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.'));
    643                                 }
    644                         }
    645                 }
    646                 @closedir( $themes_dir );
    647         }
    648         return $theme_files;
     400        return $found_themes;
    649401}
    650402
    651403/**
     
    725477                        $theme_root = $theme_roots[$stylesheet_or_template];
    726478        }
    727479
    728         return $theme_root;
     480        return str_replace( WP_CONTENT_DIR, '', $theme_root );
    729481}
    730482
    731483/**
  • wp-includes/deprecated.php

     
    29062906 */
    29072907function debug_fclose( $fp ) {
    29082908        _deprecated_function( __FUNCTION__, 'error_log()' );
     2909}
     2910
     2911/**
     2912 * Retrieve list of themes with theme data in theme directory.
     2913 *
     2914 * The theme is broken, if it doesn't have a parent theme and is missing either
     2915 * style.css and, or index.php. If the theme has a parent theme then it is
     2916 * broken, if it is missing style.css; index.php is optional.
     2917 *
     2918 * @since 1.5.0
     2919 * @global array $wp_themes Stores the working themes.
     2920 *
     2921 * @return array Theme list with theme data.
     2922 */
     2923function get_themes() {
     2924        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_themes()' );
     2925
     2926        global $wp_themes;
     2927        if ( isset( $wp_themes ) )
     2928                return $wp_themes;
     2929
     2930        $themes = wp_get_themes();
     2931        $wp_themes = array();
     2932
     2933        foreach ( $themes as $theme ) {
     2934                $wp_themes[ $theme->get('Name') ] = $theme;
     2935        }
     2936
     2937        return $wp_themes;
     2938}
     2939
     2940/**
     2941 * Retrieve theme data.
     2942 *
     2943 * @since 1.5.0
     2944 *
     2945 * @param string $theme Theme name.
     2946 * @return array|null Null, if theme name does not exist. Theme data, if exists.
     2947 */
     2948function get_theme( $theme ) {
     2949        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme($stylesheet)' );
     2950
     2951        $themes = get_themes();
     2952        if ( is_array( $themes ) && array_key_exists( $theme, $themes ) )
     2953                return $themes[$theme];
     2954        return null;
    29092955}
     2956 No newline at end of file
  • wp-settings.php

     
    112112require( ABSPATH . WPINC . '/capabilities.php' );
    113113require( ABSPATH . WPINC . '/query.php' );
    114114require( ABSPATH . WPINC . '/theme.php' );
     115require( ABSPATH . WPINC . '/class-wp-theme.php' );
    115116require( ABSPATH . WPINC . '/user.php' );
    116117require( ABSPATH . WPINC . '/meta.php' );
    117118require( ABSPATH . WPINC . '/general-template.php' );
  • wp-admin/includes/ms-deprecated.php

     
    6464        _deprecated_function(__FUNCTION__, '3.0', 'is_network_only_plugin()' );
    6565        return is_network_only_plugin( $file );
    6666}
     67
     68function get_site_allowed_themes() {
     69        _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_network()' );
     70        return array_map( 'intval', WP_Theme::get_allowed_on_network() );
     71}
     72
     73function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
     74        _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_site()' );
     75        return array_map( 'intval', WP_Theme::get_allowed_on_site( $blog_id ) );
     76}
     77 No newline at end of file
  • wp-admin/includes/update.php

     
    217217}
    218218
    219219function get_theme_updates() {
    220         $themes = get_themes();
     220        $themes = wp_get_themes();
    221221        $current = get_site_transient('update_themes');
    222222        $update_themes = array();
    223223
    224         foreach ( $themes as $theme ) {
    225                 $theme = (object) $theme;
    226                 if ( isset($current->response[ $theme->Stylesheet ]) ) {
    227                         $update_themes[$theme->Stylesheet] = $theme;
    228                         $update_themes[$theme->Stylesheet]->update = $current->response[ $theme->Stylesheet ];
    229                 }
     224        foreach ( $current->response as $stylesheet => $data ) {
     225                $update_themes[ $stylesheet ] = wp_get_theme( $stylesheet );
     226                $update_themes[ $stylesheet ]->update = $data;
    230227        }
    231228
    232229        return $update_themes;
  • wp-admin/includes/upgrade.php

     
    11541154                $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" );
    11551155        }
    11561156
    1157         // 3.3-beta. Can remove before release.
    1158         if ( $wp_current_db_version > 18715 && $wp_current_db_version < 19389
    1159                 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) )
    1160                         delete_metadata( 'user', 0, 'dismissed_wp_pointers', '', true );
    1161 
    11621157        if ( $wp_current_db_version >= 11548 )
    11631158                return;
    11641159
     
    12351230                $wpdb->query("ALTER TABLE $wpdb->comments DROP INDEX comment_approved");
    12361231                $wpdb->show_errors();
    12371232        }
     1233
     1234        if ( $wp_current_db_version < 20000 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
     1235                $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" );
     1236        }
    12381237}
    12391238
    12401239/**
  • wp-admin/includes/class-wp-ms-themes-list-table.php

     
    1515        function __construct() {
    1616                global $status, $page;
    1717
    18                 $default_status = get_user_option( 'themes_last_view' );
    19                 if ( empty( $default_status ) )
    20                         $default_status = 'all';
    21                 $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : $default_status;
    22                 if ( !in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search' ) ) )
     18                $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
     19                if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search' ) ) )
    2320                        $status = 'all';
    24                 if ( $status != $default_status && 'search' != $status )
    25                         update_user_meta( get_current_user_id(), 'themes_last_view', $status );
    2621
    2722                $page = $this->get_pagenum();
    2823
     
    5550        }
    5651
    5752        function prepare_items() {
    58                 global $status, $themes, $totals, $page, $orderby, $order, $s;
     53                global $status, $totals, $page, $orderby, $order, $s;
    5954
    6055                wp_reset_vars( array( 'orderby', 'order', 's' ) );
    6156
    6257                $themes = array(
    63                         'all' => apply_filters( 'all_themes', get_themes() ),
     58                        'all' => apply_filters( 'all_themes', wp_get_themes() ),
    6459                        'search' => array(),
    6560                        'enabled' => array(),
    6661                        'disabled' => array(),
    6762                        'upgrade' => array()
    6863                );
    6964
    70                 $site_allowed_themes = get_site_allowed_themes();
    71                 if ( !$this->is_site_themes ) {
    72                         $allowed_themes = $site_allowed_themes;
    73                         $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
    74                 } else {
    75                         $allowed_themes = wpmu_get_blog_allowedthemes( $this->site_id );
     65                if ( $this->is_site_themes ) {
    7666                        $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
     67                        $allowed_where = 'site';
     68                } else {
     69                        $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
     70                        $allowed_where = 'network';
    7771                }
    7872
    79                 $current = get_site_transient( 'update_themes' );
     73                $current = current_user_can( 'update_themes' ) && ! $this->is_site_themes && get_site_transient( 'update_themes' );
    8074
    8175                foreach ( (array) $themes['all'] as $key => $theme ) {
    82                         $theme_key = $theme['Stylesheet'];
    83 
    84                         if ( isset( $allowed_themes [ $theme_key ] ) )  {
    85                                 $themes['all'][$key]['enabled'] = true;
    86                                 $themes['enabled'][$key] = $themes['all'][$key];
     76                        if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) {
     77                                unset( $themes['all'][ $key ] );
     78                                continue;
    8779                        }
    88                         else {
    89                                 $themes['all'][$key]['enabled'] = false;
    90                                 $themes['disabled'][$key] = $themes['all'][$key];
    91                         }
    92                         if ( isset( $current->response[ $theme['Template'] ] ) )
    93                                 $themes['upgrade'][$key] = $themes['all'][$key];
    9480
    95                         if ( $this->is_site_themes && isset( $site_allowed_themes[$theme_key] ) ) {
    96                                 unset( $themes['all'][$key] );
    97                                 unset( $themes['enabled'][$key] );
    98                                 unset( $themes['disabled'][$key] );
    99                         }
     81                        $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
     82                        $themes[ $filter ][ $key ] = $themes['all'][ $key ];
     83
     84                        if ( $current && isset( $current->response[ $key ] ) )
     85                                $themes['upgrade'][ $key ] = $themes['all'][ $key ];
    10086                }
    10187
    102                 if ( !current_user_can( 'update_themes' ) || $this->is_site_themes )
    103                         $themes['upgrade'] = array();
    104 
    10588                if ( $s ) {
    10689                        $status = 'search';
    10790                        $themes['search'] = array_filter( $themes['all'], array( &$this, '_search_callback' ) );
     
    11598                        $status = 'all';
    11699
    117100                $this->items = $themes[ $status ];
     101                WP_Theme::sort_by_name( $this->items );
     102
     103                $this->has_items = ! empty( $themes['all'] );
    118104                $total_this_page = $totals[ $status ];
    119105
    120106                if ( $orderby ) {
    121107                        $orderby = ucfirst( $orderby );
    122108                        $order = strtoupper( $order );
    123109
    124                         uasort( $this->items, array( &$this, '_order_callback' ) );
     110                        if ( $orderby == 'Name' ) {
     111                                if ( 'ASC' == $order )
     112                                        $this->items = array_reverse( $this->items );
     113                        } else {
     114                                uasort( $this->items, array( &$this, '_order_callback' ) );
     115                        }
    125116                }
    126117
    127118                $start = ( $page - 1 ) * $themes_per_page;
    128119
    129120                if ( $total_this_page > $themes_per_page )
    130                         $this->items = array_slice( $this->items, $start, $themes_per_page );
     121                        $this->items = array_slice( $this->items, $start, $themes_per_page, true );
    131122
    132123                $this->set_pagination_args( array(
    133124                        'total_items' => $total_this_page,
     
    140131                if ( is_null( $term ) )
    141132                        $term = stripslashes( $_REQUEST['s'] );
    142133
    143                 $search_fields = array( 'Name', 'Title', 'Description', 'Author', 'Author Name', 'Author URI', 'Template', 'Stylesheet' );
    144                 foreach ( $search_fields as $field )
    145                         if ( stripos( $theme[ $field ], $term ) !== false )
     134                foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
     135                        // Don't mark up; Do translate.
     136                        if ( false !== stripos( $theme->display( $field, false, true ), $term ) )
    146137                                return true;
     138                }
    147139
     140                if ( false !== stripos( $theme->get_stylesheet(), $term ) )
     141                        return true;
     142
     143                if ( false !== stripos( $theme->get_template(), $term ) )
     144                        return true;
     145
    148146                return false;
    149147        }
    150148
     149        // Not used by any core columns.
    151150        function _order_callback( $theme_a, $theme_b ) {
    152151                global $orderby, $order;
    153152
    154                 $a = $theme_a[$orderby];
    155                 $b = $theme_b[$orderby];
     153                $a = $theme_a[ $orderby ];
     154                $b = $theme_b[ $orderby ];
    156155
    157156                if ( $a == $b )
    158157                        return 0;
     
    164163        }
    165164
    166165        function no_items() {
    167                 global $themes;
    168 
    169                 if ( !empty( $themes['all'] ) )
     166                if ( ! $$this->has_items )
    170167                        _e( 'No themes found.' );
    171168                else
    172169                        _e( 'You do not appear to have any themes available at this time.' );
     
    264261
    265262                $context = $status;
    266263
    267                 if ( $this->is_site_themes )
     264                if ( $this->is_site_themes ) {
    268265                        $url = "site-themes.php?id={$this->site_id}&amp;";
    269                 else
     266                        $allowed = $theme->is_allowed( 'site', $this->site_id );
     267                } else {
    270268                        $url = 'themes.php?';
     269                        $allowed = $theme->is_allowed( 'network' );
     270                }
    271271
    272272                // preorder
    273273                $actions = array(
     
    277277                        'delete' => ''
    278278                );
    279279
    280                 $theme_key = $theme['Stylesheet'];
     280                $theme_key = $theme->get_stylesheet();
    281281
    282                 if ( empty( $theme['enabled'] ) )
     282                if ( ! $allowed )
    283283                        $actions['enable'] = '<a href="' . esc_url( wp_nonce_url($url . 'action=enable&amp;theme=' . $theme_key . '&amp;paged=' . $page . '&amp;s=' . $s, 'enable-theme_' . $theme_key) ) . '" title="' . esc_attr__('Enable this theme') . '" class="edit">' . ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . '</a>';
    284284                else
    285285                        $actions['disable'] = '<a href="' . esc_url( wp_nonce_url($url . 'action=disable&amp;theme=' . $theme_key . '&amp;paged=' . $page . '&amp;s=' . $s, 'disable-theme_' . $theme_key) ) . '" title="' . esc_attr__('Disable this theme') . '">' . ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . '</a>';
    286286
    287287                if ( current_user_can('edit_themes') )
    288                         $actions['edit'] = '<a href="' . esc_url('theme-editor.php?theme=' . urlencode( $theme['Name'] )) . '" title="' . esc_attr__('Open this theme in the Theme Editor') . '" class="edit">' . __('Edit') . '</a>';
     288                        $actions['edit'] = '<a href="' . esc_url('theme-editor.php?theme=' .  $theme_key ) . '" title="' . esc_attr__('Open this theme in the Theme Editor') . '" class="edit">' . __('Edit') . '</a>';
    289289
    290                 if ( empty( $theme['enabled'] ) && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $theme_key != get_option( 'stylesheet' ) && $theme_key != get_option( 'template' ) )
     290                if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $theme_key != get_option( 'stylesheet' ) && $theme_key != get_option( 'template' ) )
    291291                        $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( 'themes.php?action=delete-selected&amp;checked[]=' . $theme_key . '&amp;theme_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'bulk-themes' ) ) . '" title="' . esc_attr__( 'Delete this theme' ) . '" class="delete">' . __( 'Delete' ) . '</a>';
    292292
    293293                $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme_key, $theme, $context );
    294294                $actions = apply_filters( "theme_action_links_$theme_key", $actions, $theme_key, $theme, $context );
    295295
    296                 $class = empty( $theme['enabled'] ) ? 'inactive' : 'active';
    297                 $checkbox_id = "checkbox_" . md5($theme['Name']);
    298                 $checkbox = "<input type='checkbox' name='checked[]' value='" . esc_attr( $theme_key ) . "' id='" . $checkbox_id . "' /><label class='screen-reader-text' for='" . $checkbox_id . "' >" . __('Select') . " " . $theme['Name'] . "</label>";
     296                $class = ! $allowed ? 'inactive' : 'active';
     297                $checkbox_id = "checkbox_" . md5( $theme->get('Name') );
     298                $checkbox = "<input type='checkbox' name='checked[]' value='" . esc_attr( $theme_key ) . "' id='" . $checkbox_id . "' /><label class='screen-reader-text' for='" . $checkbox_id . "' >" . __('Select') . " " . $theme->display('Name') . "</label>";
    299299
    300                 $description = '<p>' . $theme['Description'] . '</p>';
    301                 $theme_name = $theme['Name'];
     300                $description = '<p>' . $theme->display( 'Description' ) . '</p>';
    302301
    303                 $id = sanitize_title( $theme_name );
     302                $id = sanitize_html_class( $theme->get_stylesheet() );
    304303
    305304                echo "<tr id='$id' class='$class'>";
    306305
     
    316315                                        echo "<th scope='row' class='check-column'>$checkbox</th>";
    317316                                        break;
    318317                                case 'name':
    319                                         echo "<td class='theme-title'$style><strong>$theme_name</strong>";
     318                                        echo "<td class='theme-title'$style><strong>" . $theme->display('Name') . "</strong>";
    320319                                        echo $this->row_actions( $actions, true );
    321320                                        echo "</td>";
    322321                                        break;
    323322                                case 'description':
    324323                                        echo "<td class='column-description desc'$style>
    325                                                 <div class='theme-description'>$description</div>
     324                                                <div class='theme-description'>" . $theme->display( 'Description' ) . "</div>
    326325                                                <div class='$class second theme-version-author-uri'>";
    327326
    328327                                        $theme_meta = array();
    329328
    330                                         if ( !empty( $theme['Version'] ) )
    331                                                 $theme_meta[] = sprintf( __( 'Version %s' ), $theme['Version'] );
     329                                        if ( $theme->get('Version') )
     330                                                $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display('Version') );
    332331
    333                                         if ( !empty( $theme['Author'] ) )
    334                                                 $theme_meta[] = sprintf( __( 'By %s' ), $theme['Author'] );
     332                                        if ( $theme->get('Author') )
     333                                                $theme_meta[] = sprintf( __( 'By %s' ), $theme->display('Author') );
    335334
    336                                         if ( !empty( $theme['Theme URI'] ) )
    337                                                 $theme_meta[] = '<a href="' . $theme['Theme URI'] . '" title="' . esc_attr__( 'Visit theme homepage' ) . '">' . __( 'Visit Theme Site' ) . '</a>';
     335                                        if ( $theme->get('ThemeURI') )
     336                                                $theme_meta[] = '<a href="' . $theme->display('ThemeURI') . '" title="' . esc_attr__( 'Visit theme homepage' ) . '">' . __( 'Visit Theme Site' ) . '</a>';
    338337
    339338                                        $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $theme_key, $theme, $status );
    340339                                        echo implode( ' | ', $theme_meta );
  • wp-admin/includes/dashboard.php

     
    383383        echo "\n\t</table>\n\t</div>";
    384384
    385385        echo "\n\t".'<div class="versions">';
    386         $ct = current_theme_info();
     386        $theme = wp_get_theme();
    387387
    388388        echo "\n\t<p>";
    389389
    390         if ( empty( $ct->stylesheet_dir ) ) {
     390        if ( $theme->errors() ) {
    391391                if ( ! is_multisite() || is_super_admin() )
    392392                        echo '<span class="error-message">' . __('ERROR: The themes directory is either empty or doesn&#8217;t exist. Please check your installation.') . '</span>';
    393393        } elseif ( ! empty($wp_registered_sidebars) ) {
     
    401401                }
    402402                $num = number_format_i18n( $num_widgets );
    403403
    404                 $switch_themes = $ct->title;
     404                $switch_themes = $theme->display('Name');
    405405                if ( current_user_can( 'switch_themes') )
    406406                        $switch_themes = '<a href="themes.php">' . $switch_themes . '</a>';
    407407                if ( current_user_can( 'edit_theme_options' ) ) {
     
    411411                }
    412412        } else {
    413413                if ( current_user_can( 'switch_themes' ) )
    414                         printf( __('Theme <span class="b"><a href="themes.php">%1$s</a></span>'), $ct->title );
     414                        printf( __('Theme <span class="b"><a href="themes.php">%1$s</a></span>'), $theme->display('Name') );
    415415                else
    416                         printf( __('Theme <span class="b">%1$s</span>'), $ct->title );
     416                        printf( __('Theme <span class="b">%1$s</span>'), $theme->display('Name') );
    417417        }
    418418        echo '</p>';
    419419
     
    13131313        <div class="welcome-panel-column welcome-panel-last">
    13141314                <h4><span class="icon16 icon-appearance"></span> <?php _e( 'Customize Your Site' ); ?></h4>
    13151315                <?php
    1316                 $ct = current_theme_info();
    1317                 if ( empty ( $ct->stylesheet_dir ) ) :
     1316                $theme = wp_get_theme();
     1317                if ( $theme->errors() ) :
    13181318                        echo '<p>';
    13191319                        printf( __( '<a href="%s">Install a theme</a> to get started customizing your site.' ), esc_url( admin_url( 'themes.php' ) ) );
    13201320                        echo '</p>';
    13211321                else:
    13221322                        $customize_links = array();
    1323                         if ( 'twentyeleven' == $ct->stylesheet )
     1323                        if ( 'twentyeleven' == $theme->get_stylesheet() )
    13241324                                $customize_links[] = sprintf( __( '<a href="%s">Choose light or dark</a>' ), esc_url( admin_url( 'themes.php?page=theme_options' ) ) );
    13251325
    13261326                        if ( current_theme_supports( 'custom-background' ) )
     
    13341334
    13351335                        if ( ! empty( $customize_links ) ) {
    13361336                                echo '<p>';
    1337                                 printf( __( 'Use the current theme &mdash; %1$s &mdash; or <a href="%2$s">choose a new one</a>. If you stick with %3$s, here are a few ways to make your site look unique.' ), $ct->title, esc_url( admin_url( 'themes.php' ) ), $ct->title );
     1337                                printf( __( 'Use the current theme &mdash; %1$s &mdash; or <a href="%2$s">choose a new one</a>. If you stick with %1$s, here are a few ways to make your site look unique.' ), $theme->display('Name'), esc_url( admin_url( 'themes.php' ) ) );
    13381338                                echo '</p>';
    13391339                        ?>
    13401340                        <ul>
     
    13451345                        <?php
    13461346                        } else {
    13471347                                echo '<p>';
    1348                                 printf( __( 'Use the current theme &mdash; %1$s &mdash; or <a href="%2$s">choose a new one</a>.' ), $ct->title, esc_url( admin_url( 'themes.php' ) ) );
     1348                                printf( __( 'Use the current theme &mdash; %1$s &mdash; or <a href="%2$s">choose a new one</a>.' ), $this->display('Name'), esc_url( admin_url( 'themes.php' ) ) );
    13491349                                echo '</p>';
    13501350                        }
    13511351                endif; ?>
  • wp-admin/includes/deprecated.php

     
    879879                $screen = convert_to_screen( $screen );
    880880
    881881        WP_Screen::add_old_compat_help( $screen, $help );
     882}
     883
     884/**
     885 * Get the allowed themes for the current blog.
     886 *
     887 * @since 3.0.0
     888 * @deprecated 3.4.0
     889 * @deprecated Use wp_get_themes()
     890 * @see wp_get_themes()
     891 *
     892 * @return array $themes Array of allowed themes.
     893 */
     894function get_allowed_themes() {
     895        _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'allowed' => true ) )" );
     896
     897        $themes = wp_get_themes( array( 'allowed' => true ) );
     898
     899        $wp_themes = array();
     900        foreach ( $themes as $theme ) {
     901                $wp_themes[ $theme->get('Name') ] = $theme;
     902        }
     903
     904        return $wp_themes;
     905}
     906
     907/**
     908 * {@internal Missing Short Description}}
     909 *
     910 * @since 1.5.0
     911 *
     912 * @return unknown
     913 */
     914function get_broken_themes() {
     915        _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'errors' => true )" );
     916
     917        $themes = wp_get_themes( array( 'errors' => true ) );
     918        $broken = array();
     919        foreach ( $themes as $theme ) {
     920                $broken[ $theme->get('Name') ] = array(
     921                        'Title' => $theme->get('Name'),
     922                        'Description' => $theme->errors()->get_error_message(),
     923                );
     924        }
     925        return $broken;
     926}
     927
     928/**
     929 * {@internal Missing Short Description}}
     930 *
     931 * @since 2.0.0
     932 *
     933 * @return unknown
     934 */
     935function current_theme_info() {
     936        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' );
     937
     938        return wp_get_theme();
    882939}
     940 No newline at end of file
  • wp-admin/includes/schema.php

     
    343343
    344344        $template = WP_DEFAULT_THEME;
    345345        // If default theme is a child theme, we need to get its template
    346         foreach ( (array) get_themes() as $theme ) {
    347                 if ( WP_DEFAULT_THEME == $theme['Stylesheet'] ) {
    348                         $template = $theme['Template'];
    349                         break;
    350                 }
    351         }
     346        $theme = wp_get_theme( $template );
     347        if ( ! $theme->errors() )
     348                $template = $theme->get_template();
    352349
    353350        $timezone_string = '';
    354351        $gmt_offset = 0;
  • wp-admin/includes/theme.php

     
    77 */
    88
    99/**
    10  * {@internal Missing Short Description}}
    11  *
    12  * @since 2.0.0
    13  *
    14  * @return unknown
    15  */
    16 function current_theme_info() {
    17         $themes = get_themes();
    18         $current_theme = get_current_theme();
    19 
    20         if ( ! $themes ) {
    21                 $ct = new stdClass;
    22                 $ct->name = $current_theme;
    23                 return $ct;
    24         }
    25 
    26         if ( ! isset( $themes[$current_theme] ) ) {
    27                 delete_option( 'current_theme' );
    28                 $current_theme = get_current_theme();
    29         }
    30 
    31         $ct = new stdClass;
    32         $ct->name = $current_theme;
    33         $ct->title = $themes[$current_theme]['Title'];
    34         $ct->version = $themes[$current_theme]['Version'];
    35         $ct->parent_theme = $themes[$current_theme]['Parent Theme'];
    36         $ct->template_dir = $themes[$current_theme]['Template Dir'];
    37         $ct->stylesheet_dir = $themes[$current_theme]['Stylesheet Dir'];
    38         $ct->template = $themes[$current_theme]['Template'];
    39         $ct->stylesheet = $themes[$current_theme]['Stylesheet'];
    40         $ct->screenshot = $themes[$current_theme]['Screenshot'];
    41         $ct->description = $themes[$current_theme]['Description'];
    42         $ct->author = $themes[$current_theme]['Author'];
    43         $ct->tags = $themes[$current_theme]['Tags'];
    44         $ct->theme_root = $themes[$current_theme]['Theme Root'];
    45         $ct->theme_root_uri = $themes[$current_theme]['Theme Root URI'];
    46         return $ct;
    47 }
    48 
    49 /**
    5010 * Remove a theme
    5111 *
    5212 * @since 2.8.0
     
    11474}
    11575
    11676/**
    117  * {@internal Missing Short Description}}
    118  *
    119  * @since 1.5.0
    120  *
    121  * @return unknown
    122  */
    123 function get_broken_themes() {
    124         global $wp_broken_themes;
    125 
    126         get_themes();
    127         return $wp_broken_themes;
    128 }
    129 
    130 /**
    131  * Get the allowed themes for the current blog.
    132  *
    133  * @since 3.0.0
    134  *
    135  * @uses get_themes()
    136  * @uses current_theme_info()
    137  * @uses get_site_allowed_themes()
    138  * @uses wpmu_get_blog_allowedthemes
    139  *
    140  * @return array $themes Array of allowed themes.
    141  */
    142 function get_allowed_themes() {
    143         if ( !is_multisite() )
    144                 return get_themes();
    145 
    146         $themes = get_themes();
    147         $ct = current_theme_info();
    148         $allowed_themes = apply_filters("allowed_themes", get_site_allowed_themes() );
    149         if ( $allowed_themes == false )
    150                 $allowed_themes = array();
    151 
    152         $blog_allowed_themes = wpmu_get_blog_allowedthemes();
    153         if ( is_array( $blog_allowed_themes ) )
    154                 $allowed_themes = array_merge( $allowed_themes, $blog_allowed_themes );
    155 
    156         if ( isset( $allowed_themes[ esc_html( $ct->stylesheet ) ] ) == false )
    157                 $allowed_themes[ esc_html( $ct->stylesheet ) ] = true;
    158 
    159         reset( $themes );
    160         foreach ( $themes as $key => $theme ) {
    161                 if ( isset( $allowed_themes[ esc_html( $theme[ 'Stylesheet' ] ) ] ) == false )
    162                         unset( $themes[ $key ] );
    163         }
    164         reset( $themes );
    165 
    166         return $themes;
    167 }
    168 
    169 /**
    17077 * Get the Page Templates available in this theme
    17178 *
    17279 * @since 1.5.0
     
    17481 * @return array Key is the template name, value is the filename of the template
    17582 */
    17683function get_page_templates() {
    177         $themes = get_themes();
    178         $theme = get_current_theme();
    179         $templates = $themes[$theme]['Template Files'];
    180         $page_templates = array();
    181 
    182         if ( is_array( $templates ) ) {
    183                 $base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );
    184 
    185                 foreach ( $templates as $template ) {
    186                         $basename = str_replace($base, '', $template);
    187 
    188                         // don't allow template files in subdirectories
    189                         if ( false !== strpos($basename, '/') )
    190                                 continue;
    191 
    192                         if ( 'functions.php' == $basename )
    193                                 continue;
    194 
    195                         $template_data = implode( '', file( $template ));
    196 
    197                         $name = '';
    198                         if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name ) )
    199                                 $name = _cleanup_header_comment($name[1]);
    200 
    201                         if ( !empty( $name ) ) {
    202                                 $page_templates[trim( $name )] = $basename;
    203                         }
    204                 }
    205         }
    206 
    207         return $page_templates;
     84        return wp_get_theme()->get_page_templates();
    20885}
    20986
    21087/**
     
    240117        if ( !isset($themes_update) )
    241118                $themes_update = get_site_transient('update_themes');
    242119
    243         if ( is_object($theme) && isset($theme->stylesheet) )
    244                 $stylesheet = $theme->stylesheet;
    245         elseif ( is_array($theme) && isset($theme['Stylesheet']) )
    246                 $stylesheet = $theme['Stylesheet'];
    247         else
    248                 return false; //No valid info passed.
     120        if ( ! is_a( $theme, 'WP_Theme' ) )
     121                return;
    249122
     123        $stylesheet = $theme->get_stylesheet();
     124
    250125        if ( isset($themes_update->response[ $stylesheet ]) ) {
    251126                $update = $themes_update->response[ $stylesheet ];
    252                 $theme_name = is_object($theme) ? $theme->name : (is_array($theme) ? $theme['Name'] : '');
     127                $theme_name = $theme->get('Name');
    253128                $details_url = add_query_arg(array('TB_iframe' => 'true', 'width' => 1024, 'height' => 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list.
    254129                $update_url = wp_nonce_url('update.php?action=upgrade-theme&amp;theme=' . urlencode($stylesheet), 'upgrade-theme_' . $stylesheet);
    255130                $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __("Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.") ) . '\') ) {return true;}return false;"';
     
    270145 *
    271146 * @since 3.1.0
    272147 *
     148 * @param bool $api Optional. Whether to hit the API for tags. Defaults to true.
    273149 * @return array Array of features keyed by category with translations keyed by slug.
    274150 */
    275 function get_theme_feature_list() {
     151function get_theme_feature_list( $api = true ) {
    276152        // Hard-coded list is used if api not accessible.
    277153        $features = array(
    278154                        __('Colors') => array(
     
    290166                                'white'   => __( 'White' ),
    291167                                'yellow'  => __( 'Yellow' ),
    292168                                'dark'    => __( 'Dark' ),
    293                                 'light'   => __( 'Light ')
     169                                'light'   => __( 'Light' )
    294170                        ),
    295171
    296172                __('Columns') => array(
     
    335211                )
    336212        );
    337213
    338         if ( !current_user_can('install_themes') )
     214        if ( ! $api || !current_user_can('install_themes') )
    339215                return $features;
    340216
    341217        if ( !$feature_list = get_site_transient( 'wporg_theme_feature_list' ) )
  • wp-admin/includes/theme-install.php

     
    265265                }
    266266        }
    267267
    268         $themes = get_themes();
    269         foreach ( (array) $themes as $this_theme ) {
    270                 if ( is_array($this_theme) && $this_theme['Stylesheet'] == $api->slug ) {
    271                         if ( version_compare( $this_theme['Version'], $api->version, '=' ) ) {
     268        $theme = wp_get_theme( $api->slug );
     269        if ( is_a( $theme, 'WP_Theme' ) ) {
     270                switch ( version_compare( $theme->get('Version'), $api->version ) ) {
     271                        case 0; // equal
    272272                                $type = 'latest_installed';
    273                         } elseif ( version_compare( $this_theme['Version'], $api->version, '>' ) ) {
     273                        case 1: // installed theme > api version
    274274                                $type = 'newer_installed';
    275                                 $newer_version = $this_theme['Version'];
    276                         }
    277                         break;
     275                                $newer_version = $theme->get('Version');
    278276                }
    279277        }
    280278?>
  • wp-admin/includes/class-wp-themes-list-table.php

     
    2424        }
    2525
    2626        function prepare_items() {
    27                 global $ct;
     27                $themes = wp_get_themes( array( 'allowed' => true ) );
    2828
    29                 $ct = current_theme_info();
    30 
    31                 $themes = get_allowed_themes();
    32 
    3329                if ( ! empty( $_REQUEST['s'] ) ) {
    3430                        $search = strtolower( stripslashes( $_REQUEST['s'] ) );
    3531                        $this->search = array_merge( $this->search, array_filter( array_map( 'trim', explode( ',', $search ) ) ) );
     
    4541
    4642                if ( $this->search || $this->features ) {
    4743                        foreach ( $themes as $key => $theme ) {
    48                                 if ( !$this->search_theme( $theme ) )
     44                                if ( ! $this->search_theme( $theme ) )
    4945                                        unset( $themes[ $key ] );
    5046                        }
    5147                }
    5248
    53                 unset( $themes[$ct->name] );
    54                 uksort( $themes, "strnatcasecmp" );
     49                unset( $themes[ get_option( 'stylesheet' ) ] );
     50                WP_Theme::sort_by_name( $themes );
    5551
    5652                $per_page = 999;
    5753                $page = $this->get_pagenum();
     
    125121
    126122        function display_rows() {
    127123                $themes = $this->items;
    128                 $theme_names = array_keys( $themes );
    129                 natcasesort( $theme_names );
    130124
    131         foreach ( $theme_names as $theme_name ) {
    132                 $class = array( 'available-theme' );
    133         ?>
    134         <div class="<?php echo join( ' ', $class ); ?>">
    135         <?php if ( !empty( $theme_name ) ) :
    136         $template = $themes[$theme_name]['Template'];
    137         $stylesheet = $themes[$theme_name]['Stylesheet'];
    138         $title = $themes[$theme_name]['Title'];
    139         $version = $themes[$theme_name]['Version'];
    140         $description = $themes[$theme_name]['Description'];
    141         $author = $themes[$theme_name]['Author'];
    142         $screenshot = $themes[$theme_name]['Screenshot'];
    143         $stylesheet_dir = $themes[$theme_name]['Stylesheet Dir'];
    144         $template_dir = $themes[$theme_name]['Template Dir'];
    145         $parent_theme = $themes[$theme_name]['Parent Theme'];
    146         $theme_root = $themes[$theme_name]['Theme Root'];
    147         $theme_root_uri = $themes[$theme_name]['Theme Root URI'];
    148         $preview_link = esc_url( add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => true, 'TB_iframe' => 'true' ), home_url( '/' ) ) );
    149         $preview_text = esc_attr( sprintf( __( 'Preview of &#8220;%s&#8221;' ), $title ) );
    150         $tags = $themes[$theme_name]['Tags'];
    151         $thickbox_class = 'thickbox thickbox-preview';
    152         $activate_link = wp_nonce_url( "themes.php?action=activate&amp;template=" . urlencode( $template ) . "&amp;stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $template );
    153         $activate_text = esc_attr( sprintf( __( 'Activate &#8220;%s&#8221;' ), $title ) );
    154         $actions = array();
    155         $actions[] = '<a href="' . $activate_link . '" class="activatelink" title="' . $activate_text . '">' . __( 'Activate' ) . '</a>';
    156         $actions[] = '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $theme_name ) ) . '">' . __( 'Preview' ) . '</a>';
    157         if ( ! is_multisite() && current_user_can( 'delete_themes' ) )
    158                 $actions[] = '<a class="submitdelete deletion" href="' . wp_nonce_url( "themes.php?action=delete&amp;template=$stylesheet", 'delete-theme_' . $stylesheet ) . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n  'Cancel' to stop, 'OK' to delete." ), $theme_name ) ) . "' );" . '">' . __( 'Delete' ) . '</a>';
    159         $actions = apply_filters( 'theme_action_links', $actions, $themes[$theme_name] );
     125                foreach ( $themes as $theme ) {
     126                        echo '<div class="available-theme">';
    160127
    161         $actions = implode ( ' | ', $actions );
    162 ?>
    163                 <a href="<?php echo $preview_link; ?>" class="<?php echo $thickbox_class; ?> screenshot">
    164 <?php if ( $screenshot ) : ?>
    165                         <img src="<?php echo $theme_root_uri . '/' . $stylesheet . '/' . $screenshot; ?>" alt="" />
    166 <?php endif; ?>
    167                 </a>
    168 <h3><?php
    169         /* translators: 1: theme title, 2: theme version, 3: theme author */
    170         printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?></h3>
     128                        $template = $theme->get_template();
     129                        $stylesheet = $theme->get_stylesheet();
    171130
    172 <span class='action-links'><?php echo $actions ?></span>
    173 <span class="separator hide-if-no-js">| </span><a href="#" class="theme-detail hide-if-no-js" tabindex='4'><?php _e('Details') ?></a>
    174 <div class="themedetaildiv hide-if-js">
    175 <p><?php echo $description; ?></p>
    176         <?php if ( current_user_can( 'edit_themes' ) && $parent_theme ) {
    177         /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?>
    178         <p><?php printf( __( 'The template files are located in <code>%2$s</code>. The stylesheet files are located in <code>%3$s</code>. <strong>%4$s</strong> uses templates from <strong>%5$s</strong>. Changes made to the templates will affect both themes.' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ), $title, $parent_theme ); ?></p>
    179 <?php } else { ?>
    180         <p><?php printf( __( 'All of this theme&#8217;s files are located in <code>%2$s</code>.' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ); ?></p>
    181 <?php } ?>
    182 <?php if ( $tags ) : ?>
    183 <p><?php _e( 'Tags:' ); ?> <?php echo join( ', ', $tags ); ?></p>
    184 <?php endif; ?>
    185 <?php endif; // end if not empty theme_name ?>
    186 </div>
    187         <?php theme_update_available( $themes[$theme_name] ); ?>
    188         </div>
    189 <?php } // end foreach $theme_names
     131                        $title = $theme->display('Name');
     132                        $version = $theme->display('Version');
     133                        $author = $theme->display('Author');
     134
     135                        $activate_link = wp_nonce_url( "themes.php?action=activate&amp;template=" . urlencode( $template ) . "&amp;stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $template );
     136                        $preview_link = esc_url( add_query_arg(
     137                                array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => true, 'TB_iframe' => 'true' ),
     138                                home_url( '/' ) ) );
     139
     140                        $actions = array();
     141                        $actions[] = '<a href="' . $activate_link . '" class="activatelink" title="'
     142                                . esc_attr( sprintf( __( 'Activate &#8220;%s&#8221;' ), $title ) ) . '">' . __( 'Activate' ) . '</a>';
     143                        $actions[] = '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="'
     144                                . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ) . '">' . __( 'Preview' ) . '</a>';
     145                        if ( ! is_multisite() && current_user_can( 'delete_themes' ) )
     146                                $actions[] = '<a class="submitdelete deletion" href="' . wp_nonce_url( "themes.php?action=delete&amp;template=$stylesheet", 'delete-theme_' . $stylesheet )
     147                                        . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n  'Cancel' to stop, 'OK' to delete." ), $title ) )
     148                                        . "' );" . '">' . __( 'Delete' ) . '</a>';
     149
     150                        $actions = apply_filters( 'theme_action_links', $actions, $theme );
     151
     152                        $actions = implode ( ' | ', $actions );
     153                        ?>
     154                        <a href="<?php echo $preview_link; ?>" class="thickbox thickbox-preview screenshot">
     155                        <?php if ( $theme->get_screenshot() ) : ?>
     156                                <img src="<?php echo esc_url( $theme->get_screenshot( 'absolute' ) ); ?>" alt="" />
     157                        <?php endif; ?>
     158                        </a>
     159                        <h3><?php
     160                        /* translators: 1: theme title, 2: theme version, 3: theme author */
     161                        printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?></h3>
     162
     163                        <span class='action-links'><?php echo $actions ?></span>
     164                        <span class="separator hide-if-no-js">| </span><a href="#" class="theme-detail hide-if-no-js" tabindex='4'><?php _e('Details') ?></a>
     165                        <div class="themedetaildiv hide-if-js">
     166                        <p><?php echo $theme->display('Description'); ?></p>
     167                        <?php if ( current_user_can( 'edit_themes' ) && $theme->parent() ) :
     168                                /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?>
     169                                <p><?php printf( __( 'The template files are located in <code>%2$s</code>. The stylesheet files are located in <code>%3$s</code>. <strong>%4$s</strong> uses templates from <strong>%5$s</strong>. Changes made to the templates will affect both themes.' ),
     170                                        $title, str_replace( WP_CONTENT_DIR, '', $theme->get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme->get_stylesheet_directory() ), $title, $theme->parent()->display('Name') ); ?></p>
     171                        <?php else :
     172                                        /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir */ ?>
     173                                <p><?php printf( __( 'All of this theme&#8217;s files are located in <code>%2$s</code>.' ),
     174                                        $title, str_replace( WP_CONTENT_DIR, '', $theme->get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme->get_stylesheet_directory() ) ); ?></p>
     175                        <?php endif; ?>
     176                        <?php
     177                        if ( $theme->get('Tags') )
     178                                printf( '<p>' . __( 'Tags: %s.' ) . '</p>', $theme->display('Tags') );
     179                        ?>
     180                        </div>
     181                        <?php theme_update_available( $theme ); ?>
     182                        </div>
     183                <?php
     184                }
    190185        }
    191186
    192187        function search_theme( $theme ) {
    193                 $matched = 0;
     188                // Search the features
     189                if ( $this->features ) {
     190                        foreach ( $this->features as $word ) {
     191                                if ( ! in_array( $word, $theme->get('Tags') ) )
     192                                        return false;
     193                        }
     194                }
    194195
    195196                // Match all phrases
    196                 if ( count( $this->search ) > 0 ) {
     197                if ( $this->search ) {
    197198                        foreach ( $this->search as $word ) {
    198                                 $matched = 0;
     199                                if ( in_array( $word, $theme->get('Tags') ) )
     200                                        continue;
    199201
    200                                 // In a tag?
    201                                 if ( in_array( $word, array_map( 'sanitize_title_with_dashes', $theme['Tags'] ) ) )
    202                                         $matched = 1;
    203 
    204                                 // In one of the fields?
    205                                 foreach ( array( 'Name', 'Title', 'Description', 'Author', 'Template', 'Stylesheet' ) AS $field ) {
    206                                         if ( stripos( $theme[$field], $word ) !== false )
    207                                                 $matched++;
     202                                foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) {
     203                                        // Don't mark up; Do translate.
     204                                        if ( false !== stripos( $theme->display( $header, false, true ), $word ) )
     205                                                continue 2;
    208206                                }
    209207
    210                                 if ( $matched == 0 )
    211                                         return false;
    212                         }
    213                 }
     208                                if ( false !== stripos( $theme->get_stylesheet(), $word ) )
     209                                        continue;
    214210
    215                 // Now search the features
    216                 if ( count( $this->features ) > 0 ) {
    217                         foreach ( $this->features as $word ) {
    218                                 // In a tag?
    219                                 if ( !in_array( $word, array_map( 'sanitize_title_with_dashes', $theme['Tags'] ) ) )
    220                                         return false;
     211                                if ( false !== stripos( $theme->get_template(), $word ) )
     212                                        continue;
     213
     214                                return false;
    221215                        }
    222216                }
    223217
    224                 // Only get here if each word exists in the tags or one of the fields
    225218                return true;
    226219        }
    227220}
  • wp-admin/includes/ms.php

     
    169169        return true;
    170170}
    171171
    172 function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
    173         $themes = get_themes();
    174 
    175         if ( $blog_id != 0 )
    176                 switch_to_blog( $blog_id );
    177 
    178         $blog_allowed_themes = get_option( 'allowedthemes' );
    179         if ( !is_array( $blog_allowed_themes ) || empty( $blog_allowed_themes ) ) { // convert old allowed_themes to new allowedthemes
    180                 $blog_allowed_themes = get_option( 'allowed_themes' );
    181 
    182                 if ( is_array( $blog_allowed_themes ) ) {
    183                         foreach( (array) $themes as $key => $theme ) {
    184                                 $theme_key = esc_html( $theme['Stylesheet'] );
    185                                 if ( isset( $blog_allowed_themes[$key] ) == true ) {
    186                                         $blog_allowedthemes[$theme_key] = 1;
    187                                 }
    188                         }
    189                         $blog_allowed_themes = $blog_allowedthemes;
    190                         add_option( 'allowedthemes', $blog_allowed_themes );
    191                         delete_option( 'allowed_themes' );
    192                 }
    193         }
    194 
    195         if ( $blog_id != 0 )
    196                 restore_current_blog();
    197 
    198         return $blog_allowed_themes;
    199 }
    200 
    201172function update_option_new_admin_email( $old_value, $value ) {
    202173        $email = get_option( 'admin_email' );
    203174        if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
     
    296267}
    297268add_action( 'admin_notices', 'new_user_email_admin_notice' );
    298269
    299 function get_site_allowed_themes() {
    300         $themes = get_themes();
    301         $allowed_themes = get_site_option( 'allowedthemes' );
    302         if ( !is_array( $allowed_themes ) || empty( $allowed_themes ) ) {
    303                 $allowed_themes = get_site_option( 'allowed_themes' ); // convert old allowed_themes format
    304                 if ( !is_array( $allowed_themes ) ) {
    305                         $allowed_themes = array();
    306                 } else {
    307                         foreach( (array) $themes as $key => $theme ) {
    308                                 $theme_key = esc_html( $theme['Stylesheet'] );
    309                                 if ( isset( $allowed_themes[ $key ] ) == true ) {
    310                                         $allowedthemes[ $theme_key ] = 1;
    311                                 }
    312                         }
    313                         $allowed_themes = $allowedthemes;
    314                 }
    315         }
    316         return $allowed_themes;
    317 }
    318 
    319270/**
    320271 * Determines if there is any upload space left in the current blog's quota.
    321272 *
  • wp-admin/themes.php

     
    9696<h2><?php echo esc_html( $title ); ?>
    9797<?php endif; ?>
    9898</h2>
    99 
    100 <h3><?php _e('Current Theme'); ?></h3>
     99<?php $ct = wp_get_theme(); ?>
     100<h3><?php _e( 'Current Theme' ); ?></h3>
    101101<div id="current-theme">
    102 <?php if ( $ct->screenshot ) : ?>
    103 <img src="<?php echo $ct->theme_root_uri . '/' . $ct->stylesheet . '/' . $ct->screenshot; ?>" alt="<?php esc_attr_e('Current theme preview'); ?>" />
     102<?php if ( $ct->get_screenshot() ) : ?>
     103<img src="<?php echo $ct->get_screenshot( 'absolute' ); ?>" alt="<?php esc_attr_e( 'Current theme preview'); ?>" />
    104104<?php endif; ?>
    105105<h4><?php
    106106        /* translators: 1: theme title, 2: theme version, 3: theme author */
    107         printf(__('%1$s %2$s by %3$s'), $ct->title, $ct->version, $ct->author) ; ?></h4>
    108 <p class="theme-description"><?php echo $ct->description; ?></p>
     107        printf( __( '%1$s %2$s by %3$s' ), $ct->display('Name'), $ct->display('Version'), $ct->display('Author') ) ; ?></h4>
     108<p class="theme-description"><?php echo $ct->display('Description'); ?></p>
    109109<div class="theme-options">
    110110        <span><?php _e( 'Options:' )?></span>
    111111        <?php
     
    117117                        if ( 'themes.php' == $item[2] || 'theme-editor.php' == $item[2] )
    118118                                continue;
    119119                        // 0 = name, 1 = capability, 2 = file
    120                         if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) ) $class = ' class="current"';
    121 
     120                        if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) )
     121                                $class = ' class="current"';
    122122                        if ( !empty($submenu[$item[2]]) ) {
    123123                                $submenu[$item[2]] = array_values($submenu[$item[2]]); // Re-index.
    124124                                $menu_hook = get_plugin_page_hook($submenu[$item[2]][0][2], $item[2]);
     
    137137        }
    138138        echo implode ( ' | ', $options );
    139139
    140         if ( $ct->tags ) : ?>
    141         <p><?php _e('Tags:'); ?> <?php echo join(', ', $ct->tags); ?></p>
     140        if ( $ct->get('Tags') ) : ?>
     141        <p><?php _e('Tags:'); ?> <?php echo $ct->display('Tags'); ?></p>
    142142        <?php endif; ?>
    143143</div>
    144144<?php theme_update_available($ct); ?>
     
    218218
    219219<?php
    220220// List broken themes, if any.
    221 $broken_themes = get_broken_themes();
    222 if ( current_user_can('edit_themes') && count( $broken_themes ) ) {
     221if ( current_user_can('edit_themes') && $broken_themes = wp_get_themes( array( 'errors' => true ) ) ) {
    223222?>
    224223
    225224<h3><?php _e('Broken Themes'); ?></h3>
     
    231230                <th><?php _e('Description'); ?></th>
    232231        </tr>
    233232<?php
    234         $theme = '';
    235 
    236         $theme_names = array_keys($broken_themes);
    237         natcasesort($theme_names);
    238 
    239         foreach ($theme_names as $theme_name) {
    240                 $name = $broken_themes[$theme_name]['Title'];
    241                 $description = $broken_themes[$theme_name]['Description'];
    242 
    243                 $theme = ('class="alternate"' == $theme) ? '' : 'class="alternate"';
     233        $alt = '';
     234        foreach ( $broken_themes as $broken_theme ) {
     235                $alt = ('class="alternate"' == $alt) ? '' : 'class="alternate"';
    244236                echo "
    245                 <tr $theme>
    246                          <td>$name</td>
    247                          <td>$description</td>
     237                <tr $alt>
     238                         <td>" . $broken_theme->get('Name') ."</td>
     239                         <td>" . $broken_theme->errors()->get_error_message() . "</td>
    248240                </tr>";
    249241        }
    250242?>
     
    254246?>
    255247</div>
    256248
    257 <?php require('./admin-footer.php'); ?>
     249<?php require('./admin-footer.php'); ?>
     250 No newline at end of file