Index: /Users/andy/Sites/wptrunk/wp-includes/theme.php =================================================================== --- /Users/andy/Sites/wptrunk/wp-includes/theme.php (revision 12015) +++ /Users/andy/Sites/wptrunk/wp-includes/theme.php (working copy) @@ -33,9 +33,22 @@ * @return string Path to current theme directory. */ function get_stylesheet_directory() { + global $wp_themes; + + if ( !isset( $wp_themes ) ) + $wp_themes = get_themes(); + + $current_theme = get_current_theme(); $stylesheet = get_stylesheet(); - $stylesheet_dir = get_theme_root() . "/$stylesheet"; - return apply_filters('stylesheet_directory', $stylesheet_dir, $stylesheet); + + foreach ( $wp_themes as $theme ) { + if ( $theme['Stylesheet'] == $stylesheet ) + $theme_root = $theme['Theme Root']; + } + + $stylesheet_dir = "$theme_root/$stylesheet"; + + return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root ); } /** @@ -46,9 +59,21 @@ * @return string */ function get_stylesheet_directory_uri() { + global $wp_themes; + + if ( !isset( $wp_themes ) ) + $wp_themes = get_themes(); + + $current_theme = get_current_theme(); $stylesheet = get_stylesheet(); - $stylesheet_dir_uri = get_theme_root_uri() . "/$stylesheet"; - return apply_filters('stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet); + + foreach ( $wp_themes as $theme ) { + if ( $theme['Stylesheet'] == $stylesheet ) + $theme_root_uri = $theme['Theme Root URI']; + } + + $stylesheet_dir_uri = "$theme_root_uri/$stylesheet"; + return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri ); } /** @@ -122,9 +147,20 @@ * @return string Template directory path. */ function get_template_directory() { + global $wp_themes; + + if ( !isset( $wp_themes ) ) + $wp_themes = get_themes(); + $template = get_template(); - $template_dir = get_theme_root() . "/$template"; - return apply_filters('template_directory', $template_dir, $template); + + foreach ( $wp_themes as $theme ) { + if ( $theme['Template'] == $template && empty( $theme['Parent Theme'] ) ) + $theme_root = $theme['Theme Root']; + } + + $template_dir = "$theme_root/$template"; + return apply_filters( 'template_directory', $template_dir, $template, $theme_root ); } /** @@ -136,9 +172,21 @@ * @return string Template directory URI. */ function get_template_directory_uri() { + global $wp_themes; + + if ( !isset( $wp_themes ) ) + $wp_themes = get_themes(); + + $current_theme = get_current_theme(); $template = get_template(); - $template_dir_uri = get_theme_root_uri() . "/$template"; - return apply_filters('template_directory_uri', $template_dir_uri, $template); + + foreach ( $wp_themes as $theme ) { + if ( $theme['Template'] == $template && empty( $theme['Parent Theme'] ) ) + $theme_root_uri = $theme['Theme Root URI']; + } + + $template_dir_uri = "$theme_root_uri/$template"; + return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri ); } /** @@ -253,65 +301,18 @@ if ( isset($wp_themes) ) return $wp_themes; - $themes = array(); - $wp_broken_themes = array(); - $theme_loc = $theme_root = get_theme_root(); - if ( '/' != WP_CONTENT_DIR ) // don't want to replace all forward slashes, see Trac #4541 - $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root); + /* Register wp-content/themes as a theme directory */ + register_theme_directory( 'themes' ); - // Files in wp-content/themes directory and one subdir down - $themes_dir = @ opendir($theme_root); - if ( !$themes_dir ) + if ( !$theme_files = search_theme_directories() ) return false; + + asort( $theme_files ); + + foreach ( (array) $theme_files as $theme_file ) { + $theme_root = $theme_file['theme_root']; + $theme_file = $theme_file['theme_file']; - while ( ($theme_dir = readdir($themes_dir)) !== false ) { - if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { - if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) - continue; - $stylish_dir = @ opendir($theme_root . '/' . $theme_dir); - $found_stylesheet = false; - while ( ($theme_file = readdir($stylish_dir)) !== false ) { - if ( $theme_file == 'style.css' ) { - $theme_files[] = $theme_dir . '/' . $theme_file; - $found_stylesheet = true; - break; - } - } - @closedir($stylish_dir); - if ( !$found_stylesheet ) { // look for themes in that dir - $subdir = "$theme_root/$theme_dir"; - $subdir_name = $theme_dir; - $theme_subdir = @ opendir( $subdir ); - while ( ($theme_dir = readdir($theme_subdir)) !== false ) { - if ( is_dir( $subdir . '/' . $theme_dir) && is_readable($subdir . '/' . $theme_dir) ) { - if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) - continue; - $stylish_dir = @ opendir($subdir . '/' . $theme_dir); - $found_stylesheet = false; - while ( ($theme_file = readdir($stylish_dir)) !== false ) { - if ( $theme_file == 'style.css' ) { - $theme_files[] = $subdir_name . '/' . $theme_dir . '/' . $theme_file; - $found_stylesheet = true; - break; - } - } - @closedir($stylish_dir); - } - } - @closedir($theme_subdir); - $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); - } - } - } - if ( is_dir( $theme_dir ) ) - @closedir( $theme_dir ); - - if ( !$themes_dir || !$theme_files ) - return $themes; - - sort($theme_files); - - foreach ( (array) $theme_files as $theme_file ) { if ( !is_readable("$theme_root/$theme_file") ) { $wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.')); continue; @@ -346,19 +347,31 @@ else continue; } + + $template = trim( $template ); - $template = trim($template); - if ( !file_exists("$theme_root/$template/index.php") ) { $parent_dir = dirname(dirname($theme_file)); if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) { - $template = "$parent_dir/$template"; + $template = "$theme_root/$parent_dir/$template"; } else { - $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.')); - continue; + /** + * The parent theme doesn't exist in the current theme's folder or sub folder + * so lets use the theme root for the parent template. + */ + $parent_theme_root = $theme_files[$template]['theme_root']; + if ( file_exists( "$parent_theme_root/$template/index.php" ) ) { + $template = "$parent_theme_root/$template"; + } else { + $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.')); + continue; + } + } + } else { + $template = trim( $theme_root . '/' . $template ); } - + $stylesheet_files = array(); $template_files = array(); @@ -367,28 +380,28 @@ while ( ($file = $stylesheet_dir->read()) !== false ) { if ( !preg_match('|^\.+$|', $file) ) { if ( preg_match('|\.css$|', $file) ) - $stylesheet_files[] = "$theme_loc/$stylesheet/$file"; + $stylesheet_files[] = "$theme_root/$stylesheet/$file"; elseif ( preg_match('|\.php$|', $file) ) - $template_files[] = "$theme_loc/$stylesheet/$file"; + $template_files[] = "$theme_root/$stylesheet/$file"; } } @ $stylesheet_dir->close(); } - $template_dir = @ dir("$theme_root/$template"); + $template_dir = @ dir("$template"); if ( $template_dir ) { while ( ($file = $template_dir->read()) !== false ) { if ( preg_match('|^\.+$|', $file) ) continue; if ( preg_match('|\.php$|', $file) ) { - $template_files[] = "$theme_loc/$template/$file"; - } elseif ( is_dir("$theme_root/$template/$file") ) { - $template_subdir = @ dir("$theme_root/$template/$file"); + $template_files[] = "$template/$file"; + } elseif ( is_dir("$template/$file") ) { + $template_subdir = @ dir("$template/$file"); while ( ($subfile = $template_subdir->read()) !== false ) { if ( preg_match('|^\.+$|', $subfile) ) continue; if ( preg_match('|\.php$|', $subfile) ) - $template_files[] = "$theme_loc/$template/$file/$subfile"; + $template_files[] = "$template/$file/$subfile"; } @ $template_subdir->close(); } @@ -422,7 +435,7 @@ } } - $themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Stylesheet' => $stylesheet, 'Template Files' => $template_files, 'Stylesheet Files' => $stylesheet_files, 'Template Dir' => $template_dir, 'Stylesheet Dir' => $stylesheet_dir, 'Status' => $theme_data['Status'], 'Screenshot' => $screenshot, 'Tags' => $theme_data['Tags']); + $themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => basename( $template ), 'Stylesheet' => $stylesheet, 'Template Files' => $template_files, 'Stylesheet Files' => $stylesheet_files, 'Template Dir' => $template_dir, 'Stylesheet Dir' => $stylesheet_dir, 'Status' => $theme_data['Status'], 'Screenshot' => $screenshot, 'Tags' => $theme_data['Tags'], 'Theme Root' => $theme_root, 'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ) ); } // Resolve theme dependencies. @@ -441,7 +454,7 @@ } $wp_themes = $themes; - + return $themes; } @@ -499,6 +512,112 @@ } /** + * Register a directory that contains themes relative to the content directory. + * + * @since 2.9.0 + * + * @return bool + */ +function register_theme_directory( $directory ) { + global $wp_theme_directories; + + /* The theme directory should be relative to the content directory */ + $registered_directory = WP_CONTENT_DIR . '/' . $directory; + + /* If this folder does not exist, return and do not register */ + if ( !file_exists( $registered_directory ) ) + return false; + + $wp_theme_directories[] = $registered_directory; + + return true; +} + +/** + * Search all registered theme directories for complete and valid themes. + * + * @since 2.9.0 + * + * @return array Valid themes found + */ +function search_theme_directories() { + global $wp_theme_directories; + global $wp_broken_themes; + + if ( empty( $wp_theme_directories ) ) + return false; + + $themes = array(); + $wp_broken_themes = array(); + + /* Loop the registered theme directories and extract all themes */ + foreach ( (array) $wp_theme_directories as $theme_root ) { + $theme_loc = $theme_root; + + /* We don't want to replace all forward slashes, see Trac #4541 */ + if ( '/' != WP_CONTENT_DIR ) + $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root); + + /* Files in the root of the current theme directory and one subdir down */ + $themes_dir = @ opendir($theme_root); + + if ( !$themes_dir ) + return false; + + while ( ($theme_dir = readdir($themes_dir)) !== false ) { + if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { + if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) + continue; + + $stylish_dir = @ opendir($theme_root . '/' . $theme_dir); + $found_stylesheet = false; + + while ( ($theme_file = readdir($stylish_dir)) !== false ) { + if ( $theme_file == 'style.css' ) { + $theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root ); + $found_stylesheet = true; + break; + } + } + @closedir($stylish_dir); + + if ( !$found_stylesheet ) { // look for themes in that dir + $subdir = "$theme_root/$theme_dir"; + $subdir_name = $theme_dir; + $theme_subdir = @ opendir( $subdir ); + + while ( ($theme_dir = readdir($theme_subdir)) !== false ) { + if ( is_dir( $subdir . '/' . $theme_dir) && is_readable($subdir . '/' . $theme_dir) ) { + if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) + continue; + + $stylish_dir = @ opendir($subdir . '/' . $theme_dir); + $found_stylesheet = false; + + while ( ($theme_file = readdir($stylish_dir)) !== false ) { + if ( $theme_file == 'style.css' ) { + $theme_files[$theme_dir] = array( 'theme_file' => $subdir_name . '/' . $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root ); + $found_stylesheet = true; + break; + } + } + @closedir($stylish_dir); + } + } + @closedir($theme_subdir); + + $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); + } + } + } + if ( is_dir( $theme_dir ) ) + @closedir( $theme_dir ); + } + + return $theme_files; +} + +/** * Retrieve path to themes directory. * * Does not have trailing slash. Index: /Users/andy/Sites/wptrunk/wp-admin/includes/theme.php =================================================================== --- /Users/andy/Sites/wptrunk/wp-admin/includes/theme.php (revision 12015) +++ /Users/andy/Sites/wptrunk/wp-admin/includes/theme.php (working copy) @@ -28,6 +28,8 @@ $ct->description = $themes[$current_theme]['Description']; $ct->author = $themes[$current_theme]['Author']; $ct->tags = $themes[$current_theme]['Tags']; + $ct->theme_root = $themes[$current_theme]['Theme Root']; + $ct->theme_root_uri = $themes[$current_theme]['Theme Root URI']; return $ct; } Index: /Users/andy/Sites/wptrunk/wp-admin/themes.php =================================================================== --- /Users/andy/Sites/wptrunk/wp-admin/themes.php (revision 12015) +++ /Users/andy/Sites/wptrunk/wp-admin/themes.php (working copy) @@ -132,16 +132,16 @@
description; ?>
parent_theme) { ?> -%2$s. The stylesheet files are located in %3$s
. %4$s uses templates from %5$s. Changes made to the templates will affect both themes.'), $ct->title, $ct->template_dir, $ct->stylesheet_dir, $ct->title, $ct->parent_theme); ?>
%2$s. The stylesheet files are located in %3$s
. %4$s uses templates from %5$s. Changes made to the templates will affect both themes.'), $ct->title, str_replace( WP_CONTENT_DIR, '', $ct->template_dir ), str_replace( WP_CONTENT_DIR, '', $ct->stylesheet_dir ), $ct->title, $ct->parent_theme); ?>
%2$s.'), $ct->title, $ct->template_dir, $ct->stylesheet_dir); ?>
+%2$s.'), $ct->title, str_replace( WP_CONTENT_DIR, '', $ct->template_dir ), str_replace( WP_CONTENT_DIR, '', $ct->stylesheet_dir ) ); ?>
tags ) : ?>tags); ?>
@@ -203,6 +203,8 @@ $stylesheet_dir = $themes[$theme_name]['Stylesheet Dir']; $template_dir = $themes[$theme_name]['Template Dir']; $parent_theme = $themes[$theme_name]['Parent Theme']; + $theme_root = $themes[$theme_name]['Theme Root']; + $theme_root_uri = $themes[$theme_name]['Theme Root URI']; $preview_link = esc_url(get_option('home') . '/'); if ( is_ssl() ) $preview_link = str_replace( 'http://', 'https://', $preview_link ); @@ -223,7 +225,7 @@ ?> - +%2$s. The stylesheet files are located in %3$s
. %4$s uses templates from %5$s. Changes made to the templates will affect both themes.'), $title, $template_dir, $stylesheet_dir, $title, $parent_theme); ?>
%2$s. The stylesheet files are located in %3$s
. %4$s uses templates from %5$s. 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); ?>
%2$s.'), $title, $template_dir, $stylesheet_dir); ?>
+%2$s.'), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ); ?>