WordPress.org

Make WordPress Core

Changeset 20020


Ignore:
Timestamp:
02/28/12 20:05:00 (6 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.