Make WordPress Core

Changeset 20020


Ignore:
Timestamp:
02/28/2012 08:05:00 PM (15 years ago)
Author:
nacin
Message:

Rewrite search_theme_directories() -- better performance and allow for caching.

  • Update it to use PHP5 scandir().
  • Don't scan individual theme dirs -- we only need to check for style.css. (Solid performance gains.)
  • Improve and simplify branching.
  • Introduce wp_cache_themes_persistently filter to enable persistent caching of the return value, based on the theme_roots transient.

see #20103.

File:
1 edited

Legend:

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

    r20018 r20020  
    572572 */
    573573function search_theme_directories() {
    574         global $wp_theme_directories, $wp_broken_themes;
     574        global $wp_theme_directories;
    575575        if ( empty( $wp_theme_directories ) )
    576576                return false;
    577577
    578         $theme_files = array();
    579         $wp_broken_themes = array();
     578        static $found_themes;
     579        if ( isset( $found_themes ) )
     580                return $found_themes;
     581
     582        $found_themes = array();
     583
     584        if ( $cache_expiration = apply_filters( 'wp_cache_themes_persistently', false, 'search_theme_directories' ) ) {
     585                $cached_roots = get_site_transient( 'theme_roots' );
     586                if ( is_array( $cached_roots ) ) {
     587                        foreach ( $cached_roots as $theme_dir => $theme_root ) {
     588                                $found_themes[ $theme_dir ] = array(
     589                                        'theme_file' => $theme_dir . '/style.css',
     590                                        'theme_root' => $theme_root,
     591                                );
     592                        }
     593                        return $found_themes;
     594                }
     595                if ( ! is_int( $cache_expiration ) )
     596                        $cache_expiration = 7200;
     597        } else {
     598                // Two hours is the default.
     599                $cache_expiration = 7200;
     600        }
    580601
    581602        /* Loop the registered theme directories and extract all themes */
    582         foreach ( (array) $wp_theme_directories as $theme_root ) {
    583                 $theme_loc = $theme_root;
    584 
    585                 /* We don't want to replace all forward slashes, see Trac #4541 */
    586                 if ( '/' != WP_CONTENT_DIR )
    587                         $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root);
    588 
    589                 /* Files in the root of the current theme directory and one subdir down */
    590                 $themes_dir = @ opendir($theme_root);
    591 
    592                 if ( !$themes_dir )
     603        foreach ( $wp_theme_directories as $theme_root ) {
     604
     605                // Start with directories in the root of the current theme directory.
     606                $dirs = @ scandir( $theme_root );
     607                if ( ! $dirs )
    593608                        return false;
    594 
    595                 while ( ($theme_dir = readdir($themes_dir)) !== false ) {
    596                         if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) {
    597                                 if ( $theme_dir[0] == '.' || $theme_dir == 'CVS' )
    598                                         continue;
    599 
    600                                 $stylish_dir = @opendir($theme_root . '/' . $theme_dir);
    601                                 $found_stylesheet = false;
    602 
    603                                 while ( ($theme_file = readdir($stylish_dir)) !== false ) {
    604                                         if ( $theme_file == 'style.css' ) {
    605                                                 $theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root );
    606                                                 $found_stylesheet = true;
    607                                                 break;
    608                                         }
     609                foreach ( $dirs as $dir ) {
     610                        if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' )
     611                                continue;
     612                        if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) {
     613                                // wp-content/themes/a-single-theme
     614                                // wp-content/themes is $theme_root, a-single-theme is $dir
     615                                $found_themes[ $dir ] = array(
     616                                        'theme_file' => $dir . '/style.css',
     617                                        'theme_root' => $theme_root,
     618                                );
     619                        } else {
     620                                $found_theme = false;
     621                                // wp-content/themes/a-folder-of-themes/*
     622                                // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs
     623                                $sub_dirs = @ scandir( $theme_root . '/' . $dir );
     624                                if ( ! $sub_dirs )
     625                                        return false;
     626                                foreach ( $sub_dirs as $sub_dir ) {
     627                                        if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' )
     628                                                continue;
     629                                        if ( ! file_exists( $theme_root . '/' . $dir . '/' . $sub_dir . '/style.css' ) )
     630                                                continue;
     631                                        $found_themes[ $dir . '/' . $sub_dir ] = array(
     632                                                'theme_file' => $dir . '/' . $sub_dir . '/style.css',
     633                                                'theme_root' => $theme_root,
     634                                        );
     635                                        $found_theme = true;
    609636                                }
    610                                 @closedir($stylish_dir);
    611 
    612                                 if ( !$found_stylesheet ) { // look for themes in that dir
    613                                         $subdir = "$theme_root/$theme_dir";
    614                                         $subdir_name = $theme_dir;
    615                                         $theme_subdirs = @opendir( $subdir );
    616 
    617                                         $found_subdir_themes = false;
    618                                         while ( ($theme_subdir = readdir($theme_subdirs)) !== false ) {
    619                                                 if ( is_dir( $subdir . '/' . $theme_subdir) && is_readable($subdir . '/' . $theme_subdir) ) {
    620                                                         if ( $theme_subdir[0] == '.' || $theme_subdir == 'CVS' )
    621                                                                 continue;
    622 
    623                                                         $stylish_dir = @opendir($subdir . '/' . $theme_subdir);
    624                                                         $found_stylesheet = false;
    625 
    626                                                         while ( ($theme_file = readdir($stylish_dir)) !== false ) {
    627                                                                 if ( $theme_file == 'style.css' ) {
    628                                                                         $theme_files["$theme_dir/$theme_subdir"] = array( 'theme_file' => $subdir_name . '/' . $theme_subdir . '/' . $theme_file, 'theme_root' => $theme_root );
    629                                                                         $found_stylesheet = true;
    630                                                                         $found_subdir_themes = true;
    631                                                                         break;
    632                                                                 }
    633                                                         }
    634                                                         @closedir($stylish_dir);
    635                                                 }
    636                                         }
    637                                         @closedir($theme_subdirs);
    638                                         if ( !$found_subdir_themes )
    639                                                 $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.'));
    640                                 }
     637                                // Never mind the above, it's just a theme missing a style.css.
     638                                // Return it; WP_Theme will catch the error.
     639                                if ( ! $found_theme )
     640                                        $found_themes[ $dir ] = array(
     641                                                'theme_file' => $dir . '/style.css',
     642                                                'theme_root' => $theme_root,
     643                                        );
    641644                        }
    642645                }
    643                 @closedir( $themes_dir );
    644         }
    645         return $theme_files;
     646        }
     647
     648        asort( $found_themes );
     649
     650        $theme_roots = array();
     651        foreach ( $found_themes as $theme_dir => $theme_data ) {
     652                $theme_roots[ $theme_dir ] = $theme_data['theme_root'];
     653        }
     654
     655        if ( $theme_roots != get_site_transient( 'theme_roots' ) )
     656                set_site_transient( 'theme_roots', $theme_roots, $cache_expiration );
     657
     658        return $found_themes;
    646659}
    647660
Note: See TracChangeset for help on using the changeset viewer.