web/wp-includes/theme.php
branchwordpress
changeset 132 4d4862461b8d
parent 109 03b0d1493584
equal deleted inserted replaced
131:a4642baaf829 132:4d4862461b8d
    32  *
    32  *
    33  * @return string Path to current theme directory.
    33  * @return string Path to current theme directory.
    34  */
    34  */
    35 function get_stylesheet_directory() {
    35 function get_stylesheet_directory() {
    36 	$stylesheet = get_stylesheet();
    36 	$stylesheet = get_stylesheet();
    37 	$stylesheet_dir = get_theme_root() . "/$stylesheet";
    37 	$theme_root = get_theme_root( $stylesheet );
    38 	return apply_filters('stylesheet_directory', $stylesheet_dir, $stylesheet);
    38 	$stylesheet_dir = "$theme_root/$stylesheet";
       
    39 
       
    40 	return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root );
    39 }
    41 }
    40 
    42 
    41 /**
    43 /**
    42  * Retrieve stylesheet directory URI.
    44  * Retrieve stylesheet directory URI.
    43  *
    45  *
    45  *
    47  *
    46  * @return string
    48  * @return string
    47  */
    49  */
    48 function get_stylesheet_directory_uri() {
    50 function get_stylesheet_directory_uri() {
    49 	$stylesheet = get_stylesheet();
    51 	$stylesheet = get_stylesheet();
    50 	$stylesheet_dir_uri = get_theme_root_uri() . "/$stylesheet";
    52 	$theme_root_uri = get_theme_root_uri( $stylesheet );
    51 	return apply_filters('stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet);
    53 	$stylesheet_dir_uri = "$theme_root_uri/$stylesheet";
       
    54 
       
    55 	return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri );
    52 }
    56 }
    53 
    57 
    54 /**
    58 /**
    55  * Retrieve URI of current theme stylesheet.
    59  * Retrieve URI of current theme stylesheet.
    56  *
    60  *
   121  *
   125  *
   122  * @return string Template directory path.
   126  * @return string Template directory path.
   123  */
   127  */
   124 function get_template_directory() {
   128 function get_template_directory() {
   125 	$template = get_template();
   129 	$template = get_template();
   126 	$template_dir = get_theme_root() . "/$template";
   130 	$theme_root = get_theme_root( $template );
   127 	return apply_filters('template_directory', $template_dir, $template);
   131 	$template_dir = "$theme_root/$template";
       
   132 
       
   133 	return apply_filters( 'template_directory', $template_dir, $template, $theme_root );
   128 }
   134 }
   129 
   135 
   130 /**
   136 /**
   131  * Retrieve theme directory URI.
   137  * Retrieve theme directory URI.
   132  *
   138  *
   135  *
   141  *
   136  * @return string Template directory URI.
   142  * @return string Template directory URI.
   137  */
   143  */
   138 function get_template_directory_uri() {
   144 function get_template_directory_uri() {
   139 	$template = get_template();
   145 	$template = get_template();
   140 	$template_dir_uri = get_theme_root_uri() . "/$template";
   146 	$theme_root_uri = get_theme_root_uri( $template );
   141 	return apply_filters('template_directory_uri', $template_dir_uri, $template);
   147 	$template_dir_uri = "$theme_root_uri/$template";
       
   148 
       
   149 	return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri );
   142 }
   150 }
   143 
   151 
   144 /**
   152 /**
   145  * Retrieve theme data from parsed theme file.
   153  * Retrieve theme data from parsed theme file.
   146  *
   154  *
   160  *
   168  *
   161  * @param string $theme_file Theme file path.
   169  * @param string $theme_file Theme file path.
   162  * @return array Theme data.
   170  * @return array Theme data.
   163  */
   171  */
   164 function get_theme_data( $theme_file ) {
   172 function get_theme_data( $theme_file ) {
       
   173 	$default_headers = array( 
       
   174 		'Name' => 'Theme Name', 
       
   175 		'URI' => 'Theme URI', 
       
   176 		'Description' => 'Description', 
       
   177 		'Author' => 'Author', 
       
   178 		'AuthorURI' => 'Author URI',
       
   179 		'Version' => 'Version', 
       
   180 		'Template' => 'Template', 
       
   181 		'Status' => 'Status', 
       
   182 		'Tags' => 'Tags'
       
   183 		);
       
   184 
   165 	$themes_allowed_tags = array(
   185 	$themes_allowed_tags = array(
   166 		'a' => array(
   186 		'a' => array(
   167 			'href' => array(),'title' => array()
   187 			'href' => array(),'title' => array()
   168 			),
   188 			),
   169 		'abbr' => array(
   189 		'abbr' => array(
   175 		'code' => array(),
   195 		'code' => array(),
   176 		'em' => array(),
   196 		'em' => array(),
   177 		'strong' => array()
   197 		'strong' => array()
   178 	);
   198 	);
   179 
   199 
   180 	$theme_data = implode( '', file( $theme_file ) );
   200 	$theme_data = get_file_data( $theme_file, $default_headers, 'theme' );
   181 	$theme_data = str_replace ( '\r', '\n', $theme_data );
   201 
   182 	if ( preg_match( '|Theme Name:(.*)$|mi', $theme_data, $theme_name ) )
   202 	$theme_data['Name'] = $theme_data['Title'] = wp_kses( $theme_data['Name'], $themes_allowed_tags );
   183 		$name = $theme = wp_kses( _cleanup_header_comment($theme_name[1]), $themes_allowed_tags );
   203 
       
   204 	$theme_data['URI'] = esc_url( $theme_data['URI'] );
       
   205 
       
   206 	$theme_data['Description'] = wptexturize( wp_kses( $theme_data['Description'], $themes_allowed_tags ) );
       
   207 
       
   208 	$theme_data['AuthorURI'] = esc_url( $theme_data['AuthorURI'] );
       
   209 
       
   210 	$theme_data['Template'] = wp_kses( $theme_data['Template'], $themes_allowed_tags );
       
   211 
       
   212 	$theme_data['Version'] = wp_kses( $theme_data['Version'], $themes_allowed_tags );
       
   213 
       
   214 	if ( $theme_data['Status'] == '' )
       
   215 		$theme_data['Status'] = 'publish';
   184 	else
   216 	else
   185 		$name = $theme = '';
   217 		$theme_data['Status'] = wp_kses( $theme_data['Status'], $themes_allowed_tags );
   186 
   218 
   187 	if ( preg_match( '|Theme URI:(.*)$|mi', $theme_data, $theme_uri ) )
   219 	if ( $theme_data['Tags'] == '' )
   188 		$theme_uri = esc_url( _cleanup_header_comment($theme_uri[1]) );
   220 		$theme_data['Tags'] = array();
   189 	else
   221 	else
   190 		$theme_uri = '';
   222 		$theme_data['Tags'] = array_map( 'trim', explode( ',', wp_kses( $theme_data['Tags'], array() ) ) );
   191 
   223 
   192 	if ( preg_match( '|Description:(.*)$|mi', $theme_data, $description ) )
   224 	if ( $theme_data['Author'] == '' ) {
   193 		$description = wptexturize( wp_kses( _cleanup_header_comment($description[1]), $themes_allowed_tags ) );
   225 		$theme_data['Author'] = __('Anonymous');
   194 	else
   226 	} else {
   195 		$description = '';
   227 		if ( empty( $theme_data['AuthorURI'] ) ) {
   196 
   228 			$theme_data['Author'] = wp_kses( $theme_data['Author'], $themes_allowed_tags );
   197 	if ( preg_match( '|Author URI:(.*)$|mi', $theme_data, $author_uri ) )
       
   198 		$author_uri = esc_url( _cleanup_header_comment($author_uri[1]) );
       
   199 	else
       
   200 		$author_uri = '';
       
   201 
       
   202 	if ( preg_match( '|Template:(.*)$|mi', $theme_data, $template ) )
       
   203 		$template = wp_kses( _cleanup_header_comment($template[1]), $themes_allowed_tags );
       
   204 	else
       
   205 		$template = '';
       
   206 
       
   207 	if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) )
       
   208 		$version = wp_kses( _cleanup_header_comment($version[1]), $themes_allowed_tags );
       
   209 	else
       
   210 		$version = '';
       
   211 
       
   212 	if ( preg_match('|Status:(.*)|i', $theme_data, $status) )
       
   213 		$status = wp_kses( _cleanup_header_comment($status[1]), $themes_allowed_tags );
       
   214 	else
       
   215 		$status = 'publish';
       
   216 
       
   217 	if ( preg_match('|Tags:(.*)|i', $theme_data, $tags) )
       
   218 		$tags = array_map( 'trim', explode( ',', wp_kses( _cleanup_header_comment($tags[1]), array() ) ) );
       
   219 	else
       
   220 		$tags = array();
       
   221 
       
   222 	if ( preg_match( '|Author:(.*)$|mi', $theme_data, $author_name ) ) {
       
   223 		if ( empty( $author_uri ) ) {
       
   224 			$author = wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags );
       
   225 		} else {
   229 		} else {
   226 			$author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage' ), wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags ) );
   230 			$theme_data['Author'] = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $theme_data['AuthorURI'], __( 'Visit author homepage' ), wp_kses( $theme_data['Author'], $themes_allowed_tags ) );
   227 		}
   231 		}
   228 	} else {
       
   229 		$author = __('Anonymous');
       
   230 	}
   232 	}
   231 
   233 
   232 	return array( 'Name' => $name, 'Title' => $theme, 'URI' => $theme_uri, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Status' => $status, 'Tags' => $tags );
   234 	return $theme_data;
   233 }
   235 }
   234 
   236 
   235 /**
   237 /**
   236  * Retrieve list of themes with theme data in theme directory.
   238  * Retrieve list of themes with theme data in theme directory.
   237  *
   239  *
   251 	global $wp_themes, $wp_broken_themes;
   253 	global $wp_themes, $wp_broken_themes;
   252 
   254 
   253 	if ( isset($wp_themes) )
   255 	if ( isset($wp_themes) )
   254 		return $wp_themes;
   256 		return $wp_themes;
   255 
   257 
   256 	$themes = array();
   258 	/* Register the default root as a theme directory */
   257 	$wp_broken_themes = array();
   259 	register_theme_directory( get_theme_root() );
   258 	$theme_loc = $theme_root = get_theme_root();
   260 
   259 	if ( '/' != WP_CONTENT_DIR ) // don't want to replace all forward slashes, see Trac #4541
   261 	if ( !$theme_files = search_theme_directories() )
   260 		$theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root);
       
   261 
       
   262 	// Files in wp-content/themes directory and one subdir down
       
   263 	$themes_dir = @ opendir($theme_root);
       
   264 	if ( !$themes_dir )
       
   265 		return false;
   262 		return false;
   266 
   263 
   267 	while ( ($theme_dir = readdir($themes_dir)) !== false ) {
   264 	asort( $theme_files );
   268 		if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) {
   265 
   269 			if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' )
   266 	$wp_themes = array();
   270 				continue;
       
   271 			$stylish_dir = @ opendir($theme_root . '/' . $theme_dir);
       
   272 			$found_stylesheet = false;
       
   273 			while ( ($theme_file = readdir($stylish_dir)) !== false ) {
       
   274 				if ( $theme_file == 'style.css' ) {
       
   275 					$theme_files[] = $theme_dir . '/' . $theme_file;
       
   276 					$found_stylesheet = true;
       
   277 					break;
       
   278 				}
       
   279 			}
       
   280 			@closedir($stylish_dir);
       
   281 			if ( !$found_stylesheet ) { // look for themes in that dir
       
   282 				$subdir = "$theme_root/$theme_dir";
       
   283 				$subdir_name = $theme_dir;
       
   284 				$theme_subdir = @ opendir( $subdir );
       
   285 				while ( ($theme_dir = readdir($theme_subdir)) !== false ) {
       
   286 					if ( is_dir( $subdir . '/' . $theme_dir) && is_readable($subdir . '/' . $theme_dir) ) {
       
   287 						if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' )
       
   288 							continue;
       
   289 						$stylish_dir = @ opendir($subdir . '/' . $theme_dir);
       
   290 						$found_stylesheet = false;
       
   291 						while ( ($theme_file = readdir($stylish_dir)) !== false ) {
       
   292 							if ( $theme_file == 'style.css' ) {
       
   293 								$theme_files[] = $subdir_name . '/' . $theme_dir . '/' . $theme_file;
       
   294 								$found_stylesheet = true;
       
   295 								break;
       
   296 							}
       
   297 						}
       
   298 						@closedir($stylish_dir);
       
   299 					}
       
   300 				}
       
   301 				@closedir($theme_subdir);
       
   302 				$wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.'));
       
   303 			}
       
   304 		}
       
   305 	}
       
   306 	if ( is_dir( $theme_dir ) )
       
   307 		@closedir( $theme_dir );
       
   308 
       
   309 	if ( !$themes_dir || !$theme_files )
       
   310 		return $themes;
       
   311 
       
   312 	sort($theme_files);
       
   313 
   267 
   314 	foreach ( (array) $theme_files as $theme_file ) {
   268 	foreach ( (array) $theme_files as $theme_file ) {
       
   269 		$theme_root = $theme_file['theme_root'];
       
   270 		$theme_file = $theme_file['theme_file'];
       
   271 
   315 		if ( !is_readable("$theme_root/$theme_file") ) {
   272 		if ( !is_readable("$theme_root/$theme_file") ) {
   316 			$wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.'));
   273 			$wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.'));
   317 			continue;
   274 			continue;
   318 		}
   275 		}
   319 
   276 
   339 			$name = dirname($theme_file);
   296 			$name = dirname($theme_file);
   340 			$title = $name;
   297 			$title = $name;
   341 		}
   298 		}
   342 
   299 
   343 		if ( empty($template) ) {
   300 		if ( empty($template) ) {
   344 			if ( file_exists(dirname("$theme_root/$theme_file/index.php")) )
   301 			if ( file_exists("$theme_root/$stylesheet/index.php") )
   345 				$template = dirname($theme_file);
   302 				$template = $stylesheet;
   346 			else
   303 			else
   347 				continue;
   304 				continue;
   348 		}
   305 		}
   349 
   306 
   350 		$template = trim($template);
   307 		$template = trim( $template );
   351 
   308 
   352 		if ( !file_exists("$theme_root/$template/index.php") ) {
   309 		if ( !file_exists("$theme_root/$template/index.php") ) {
   353 			$parent_dir = dirname(dirname($theme_file));
   310 			$parent_dir = dirname(dirname($theme_file));
   354 			if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) {
   311 			if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) {
   355 				$template = "$parent_dir/$template";
   312 				$template = "$parent_dir/$template";
       
   313 				$template_directory = "$theme_root/$template";
   356 			} else {
   314 			} else {
   357 				$wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'));
   315 				/**
   358 				continue;
   316 				 * The parent theme doesn't exist in the current theme's folder or sub folder
       
   317 				 * so lets use the theme root for the parent template.
       
   318 				 */
       
   319 				if ( isset($theme_files[$template]) && file_exists( $theme_files[$template]['theme_root'] . "/$template/index.php" ) ) {
       
   320 					$template_directory = $theme_files[$template]['theme_root'] . "/$template";
       
   321 				} else {
       
   322 					$wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'));
       
   323 					continue;
       
   324 				}
       
   325 
   359 			}
   326 			}
       
   327 		} else {
       
   328 			$template_directory = trim( $theme_root . '/' . $template );
   360 		}
   329 		}
   361 
   330 
   362 		$stylesheet_files = array();
   331 		$stylesheet_files = array();
   363 		$template_files = array();
   332 		$template_files = array();
   364 
   333 
   365 		$stylesheet_dir = @ dir("$theme_root/$stylesheet");
   334 		$stylesheet_dir = @ dir("$theme_root/$stylesheet");
   366 		if ( $stylesheet_dir ) {
   335 		if ( $stylesheet_dir ) {
   367 			while ( ($file = $stylesheet_dir->read()) !== false ) {
   336 			while ( ($file = $stylesheet_dir->read()) !== false ) {
   368 				if ( !preg_match('|^\.+$|', $file) ) {
   337 				if ( !preg_match('|^\.+$|', $file) ) {
   369 					if ( preg_match('|\.css$|', $file) )
   338 					if ( preg_match('|\.css$|', $file) )
   370 						$stylesheet_files[] = "$theme_loc/$stylesheet/$file";
   339 						$stylesheet_files[] = "$theme_root/$stylesheet/$file";
   371 					elseif ( preg_match('|\.php$|', $file) )
   340 					elseif ( preg_match('|\.php$|', $file) )
   372 						$template_files[] = "$theme_loc/$stylesheet/$file";
   341 						$template_files[] = "$theme_root/$stylesheet/$file";
   373 				}
   342 				}
   374 			}
   343 			}
   375 			@ $stylesheet_dir->close();
   344 			@ $stylesheet_dir->close();
   376 		}
   345 		}
   377 
   346 
   378 		$template_dir = @ dir("$theme_root/$template");
   347 		$template_dir = @ dir("$template_directory");
   379 		if ( $template_dir ) {
   348 		if ( $template_dir ) {
   380 			while ( ($file = $template_dir->read()) !== false ) {
   349 			while ( ($file = $template_dir->read()) !== false ) {
   381 				if ( preg_match('|^\.+$|', $file) )
   350 				if ( preg_match('|^\.+$|', $file) )
   382 					continue;
   351 					continue;
   383 				if ( preg_match('|\.php$|', $file) ) {
   352 				if ( preg_match('|\.php$|', $file) ) {
   384 					$template_files[] = "$theme_loc/$template/$file";
   353 					$template_files[] = "$template_directory/$file";
   385 				} elseif ( is_dir("$theme_root/$template/$file") ) {
   354 				} elseif ( is_dir("$template_directory/$file") ) {
   386 					$template_subdir = @ dir("$theme_root/$template/$file");
   355 					$template_subdir = @ dir("$template_directory/$file");
       
   356 					if ( !$template_subdir )
       
   357 						continue;
   387 					while ( ($subfile = $template_subdir->read()) !== false ) {
   358 					while ( ($subfile = $template_subdir->read()) !== false ) {
   388 						if ( preg_match('|^\.+$|', $subfile) )
   359 						if ( preg_match('|^\.+$|', $subfile) )
   389 							continue;
   360 							continue;
   390 						if ( preg_match('|\.php$|', $subfile) )
   361 						if ( preg_match('|\.php$|', $subfile) )
   391 							$template_files[] = "$theme_loc/$template/$file/$subfile";
   362 							$template_files[] = "$template_directory/$file/$subfile";
   392 					}
   363 					}
   393 					@ $template_subdir->close();
   364 					@ $template_subdir->close();
   394 				}
   365 				}
   395 			}
   366 			}
   396 			@ $template_dir->close();
   367 			@ $template_dir->close();
   397 		}
   368 		}
   398 
   369 
       
   370 		//Make unique and remove duplicates when stylesheet and template are the same i.e. most themes
       
   371 		$template_files = array_unique($template_files);
       
   372 		$stylesheet_files = array_unique($stylesheet_files);
       
   373 			
   399 		$template_dir = dirname($template_files[0]);
   374 		$template_dir = dirname($template_files[0]);
   400 		$stylesheet_dir = dirname($stylesheet_files[0]);
   375 		$stylesheet_dir = dirname($stylesheet_files[0]);
   401 
   376 
   402 		if ( empty($template_dir) )
   377 		if ( empty($template_dir) )
   403 			$template_dir = '/';
   378 			$template_dir = '/';
   406 
   381 
   407 		// Check for theme name collision.  This occurs if a theme is copied to
   382 		// Check for theme name collision.  This occurs if a theme is copied to
   408 		// a new theme directory and the theme header is not updated.  Whichever
   383 		// a new theme directory and the theme header is not updated.  Whichever
   409 		// theme is first keeps the name.  Subsequent themes get a suffix applied.
   384 		// theme is first keeps the name.  Subsequent themes get a suffix applied.
   410 		// The Default and Classic themes always trump their pretenders.
   385 		// The Default and Classic themes always trump their pretenders.
   411 		if ( isset($themes[$name]) ) {
   386 		if ( isset($wp_themes[$name]) ) {
   412 			if ( ('WordPress Default' == $name || 'WordPress Classic' == $name) &&
   387 			if ( ('WordPress Default' == $name || 'WordPress Classic' == $name) &&
   413 					 ('default' == $stylesheet || 'classic' == $stylesheet) ) {
   388 					 ('default' == $stylesheet || 'classic' == $stylesheet) ) {
   414 				// If another theme has claimed to be one of our default themes, move
   389 				// If another theme has claimed to be one of our default themes, move
   415 				// them aside.
   390 				// them aside.
   416 				$suffix = $themes[$name]['Stylesheet'];
   391 				$suffix = $wp_themes[$name]['Stylesheet'];
   417 				$new_name = "$name/$suffix";
   392 				$new_name = "$name/$suffix";
   418 				$themes[$new_name] = $themes[$name];
   393 				$wp_themes[$new_name] = $wp_themes[$name];
   419 				$themes[$new_name]['Name'] = $new_name;
   394 				$wp_themes[$new_name]['Name'] = $new_name;
   420 			} else {
   395 			} else {
   421 				$name = "$name/$stylesheet";
   396 				$name = "$name/$stylesheet";
   422 			}
   397 			}
   423 		}
   398 		}
   424 
   399 
   425 		$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']);
   400 		$theme_roots[$stylesheet] = str_replace( WP_CONTENT_DIR, '', $theme_root );
       
   401 		$wp_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'], 'Theme Root' => $theme_root, 'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ) );
   426 	}
   402 	}
   427 
   403 
   428 	// Resolve theme dependencies.
   404 	unset($theme_files);
   429 	$theme_names = array_keys($themes);
   405 
   430 
   406 	/* Store theme roots in the DB */
       
   407 	if ( get_site_transient( 'theme_roots' ) != $theme_roots )
       
   408 		set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours
       
   409 	unset($theme_roots);
       
   410 
       
   411 	/* Resolve theme dependencies. */
       
   412 	$theme_names = array_keys( $wp_themes );
   431 	foreach ( (array) $theme_names as $theme_name ) {
   413 	foreach ( (array) $theme_names as $theme_name ) {
   432 		$themes[$theme_name]['Parent Theme'] = '';
   414 		$wp_themes[$theme_name]['Parent Theme'] = '';
   433 		if ( $themes[$theme_name]['Stylesheet'] != $themes[$theme_name]['Template'] ) {
   415 		if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {
   434 			foreach ( (array) $theme_names as $parent_theme_name ) {
   416 			foreach ( (array) $theme_names as $parent_theme_name ) {
   435 				if ( ($themes[$parent_theme_name]['Stylesheet'] == $themes[$parent_theme_name]['Template']) && ($themes[$parent_theme_name]['Template'] == $themes[$theme_name]['Template']) ) {
   417 				if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {
   436 					$themes[$theme_name]['Parent Theme'] = $themes[$parent_theme_name]['Name'];
   418 					$wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];
   437 					break;
   419 					break;
   438 				}
   420 				}
   439 			}
   421 			}
   440 		}
   422 		}
   441 	}
   423 	}
   442 
   424 
   443 	$wp_themes = $themes;
   425 	return $wp_themes;
   444 
   426 }
   445 	return $themes;
   427 
       
   428 /**
       
   429  * Retrieve theme roots.
       
   430  *
       
   431  * @since 2.9.0
       
   432  *
       
   433  * @return array Theme roots
       
   434  */
       
   435 function get_theme_roots() {
       
   436 	$theme_roots = get_site_transient( 'theme_roots' );
       
   437 	if ( false === $theme_roots ) {
       
   438 		get_themes();
       
   439 		$theme_roots = get_site_transient( 'theme_roots' ); // this is set in get_theme()
       
   440 	}
       
   441 	return $theme_roots;
   446 }
   442 }
   447 
   443 
   448 /**
   444 /**
   449  * Retrieve theme data.
   445  * Retrieve theme data.
   450  *
   446  *
   497 
   493 
   498 	return $current_theme;
   494 	return $current_theme;
   499 }
   495 }
   500 
   496 
   501 /**
   497 /**
       
   498  * Register a directory that contains themes.
       
   499  *
       
   500  * @since 2.9.0
       
   501  *
       
   502  * @param string $directory Either the full filesystem path to a theme folder or a folder within WP_CONTENT_DIR
       
   503  * @return bool
       
   504  */
       
   505 function register_theme_directory( $directory) {
       
   506 	global $wp_theme_directories;
       
   507 
       
   508 	/* If this folder does not exist, return and do not register */
       
   509 	if ( !file_exists( $directory ) )
       
   510 			/* Try prepending as the theme directory could be relative to the content directory */
       
   511 		$registered_directory = WP_CONTENT_DIR . '/' . $directory;
       
   512 	else
       
   513 		$registered_directory = $directory;
       
   514 
       
   515 	/* If this folder does not exist, return and do not register */
       
   516 	if ( !file_exists( $registered_directory ) )
       
   517 		return false;
       
   518 
       
   519 	$wp_theme_directories[] = $registered_directory;
       
   520 
       
   521 	return true;
       
   522 }
       
   523 
       
   524 /**
       
   525  * Search all registered theme directories for complete and valid themes.
       
   526  *
       
   527  * @since 2.9.0
       
   528  *
       
   529  * @return array Valid themes found
       
   530  */
       
   531 function search_theme_directories() {
       
   532 	global $wp_theme_directories, $wp_broken_themes;
       
   533 	if ( empty( $wp_theme_directories ) )
       
   534 		return false;
       
   535 
       
   536 	$theme_files = array();
       
   537 	$wp_broken_themes = array();
       
   538 
       
   539 	/* Loop the registered theme directories and extract all themes */
       
   540 	foreach ( (array) $wp_theme_directories as $theme_root ) {
       
   541 		$theme_loc = $theme_root;
       
   542 
       
   543 		/* We don't want to replace all forward slashes, see Trac #4541 */
       
   544 		if ( '/' != WP_CONTENT_DIR )
       
   545 			$theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root);
       
   546 
       
   547 		/* Files in the root of the current theme directory and one subdir down */
       
   548 		$themes_dir = @ opendir($theme_root);
       
   549 
       
   550 		if ( !$themes_dir )
       
   551 			return false;
       
   552 
       
   553 		while ( ($theme_dir = readdir($themes_dir)) !== false ) {
       
   554 			if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) {
       
   555 				if ( $theme_dir{0} == '.' || $theme_dir == 'CVS' )
       
   556 					continue;
       
   557 
       
   558 				$stylish_dir = @opendir($theme_root . '/' . $theme_dir);
       
   559 				$found_stylesheet = false;
       
   560 
       
   561 				while ( ($theme_file = readdir($stylish_dir)) !== false ) {
       
   562 					if ( $theme_file == 'style.css' ) {
       
   563 						$theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root );
       
   564 						$found_stylesheet = true;
       
   565 						break;
       
   566 					}
       
   567 				}
       
   568 				@closedir($stylish_dir);
       
   569 
       
   570 				if ( !$found_stylesheet ) { // look for themes in that dir
       
   571 					$subdir = "$theme_root/$theme_dir";
       
   572 					$subdir_name = $theme_dir;
       
   573 					$theme_subdirs = @opendir( $subdir );
       
   574 
       
   575 					$found_subdir_themes = false;
       
   576 					while ( ($theme_subdir = readdir($theme_subdirs)) !== false ) {
       
   577 						if ( is_dir( $subdir . '/' . $theme_subdir) && is_readable($subdir . '/' . $theme_subdir) ) {
       
   578 							if ( $theme_subdir{0} == '.' || $theme_subdir == 'CVS' )
       
   579 								continue;
       
   580 
       
   581 							$stylish_dir = @opendir($subdir . '/' . $theme_subdir);
       
   582 							$found_stylesheet = false;
       
   583 
       
   584 							while ( ($theme_file = readdir($stylish_dir)) !== false ) {
       
   585 								if ( $theme_file == 'style.css' ) {
       
   586 									$theme_files["$theme_dir/$theme_subdir"] = array( 'theme_file' => $subdir_name . '/' . $theme_subdir . '/' . $theme_file, 'theme_root' => $theme_root );
       
   587 									$found_stylesheet = true;
       
   588 									$found_subdir_themes = true;
       
   589 									break;
       
   590 								}
       
   591 							}
       
   592 							@closedir($stylish_dir);
       
   593 						}
       
   594 					}
       
   595 					@closedir($theme_subdir);
       
   596 					if ( !$found_subdir_themes )
       
   597 						$wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.'));
       
   598 				}
       
   599 			}
       
   600 		}
       
   601 		if ( is_dir( $theme_dir ) )
       
   602 			@closedir( $theme_dir );
       
   603 	}
       
   604 	return $theme_files;
       
   605 }
       
   606 
       
   607 /**
   502  * Retrieve path to themes directory.
   608  * Retrieve path to themes directory.
   503  *
   609  *
   504  * Does not have trailing slash.
   610  * Does not have trailing slash.
   505  *
   611  *
   506  * @since 1.5.0
   612  * @since 1.5.0
       
   613  * @param $stylesheet_or_template The stylesheet or template name of the theme
   507  * @uses apply_filters() Calls 'theme_root' filter on path.
   614  * @uses apply_filters() Calls 'theme_root' filter on path.
   508  *
   615  *
   509  * @return string Theme path.
   616  * @return string Theme path.
   510  */
   617  */
   511 function get_theme_root() {
   618 function get_theme_root( $stylesheet_or_template = false ) {
   512 	return apply_filters('theme_root', WP_CONTENT_DIR . "/themes");
   619 	if ($stylesheet_or_template) {
       
   620 		$theme_roots = get_theme_roots();
       
   621 
       
   622 		if ( $theme_roots[$stylesheet_or_template] )
       
   623 			$theme_root = WP_CONTENT_DIR . $theme_roots[$stylesheet_or_template];
       
   624 		else
       
   625 			$theme_root = WP_CONTENT_DIR . '/themes';
       
   626 	} else {
       
   627 		$theme_root = WP_CONTENT_DIR . '/themes';
       
   628 	}
       
   629 
       
   630 	return apply_filters( 'theme_root', $theme_root );
   513 }
   631 }
   514 
   632 
   515 /**
   633 /**
   516  * Retrieve URI for themes directory.
   634  * Retrieve URI for themes directory.
   517  *
   635  *
   518  * Does not have trailing slash.
   636  * Does not have trailing slash.
   519  *
   637  *
   520  * @since 1.5.0
   638  * @since 1.5.0
       
   639  * @param $stylesheet_or_template The stylesheet or template name of the theme
   521  *
   640  *
   522  * @return string Themes URI.
   641  * @return string Themes URI.
   523  */
   642  */
   524 function get_theme_root_uri() {
   643 function get_theme_root_uri( $stylesheet_or_template = false ) {
   525 	return apply_filters('theme_root_uri', content_url('themes'), get_option('siteurl'));
   644 	$theme_roots = get_theme_roots();
       
   645 
       
   646 	if ( $theme_roots[$stylesheet_or_template] )
       
   647 		$theme_root_uri = content_url( $theme_roots[$stylesheet_or_template] );
       
   648 	else
       
   649 		$theme_root_uri = content_url( 'themes' );
       
   650 
       
   651 	return apply_filters( 'theme_root_uri', $theme_root_uri, get_option('siteurl'), $stylesheet_or_template );
   526 }
   652 }
   527 
   653 
   528 /**
   654 /**
   529  * Retrieve path to file without the use of extension.
   655  * Retrieve path to file without the use of extension.
   530  *
   656  *
   588 }
   714 }
   589 
   715 
   590 /**
   716 /**
   591  * Retrieve path of category template in current or parent template.
   717  * Retrieve path of category template in current or parent template.
   592  *
   718  *
   593  * Works by retrieving the current category ID, for example 'category-1.php' and
   719  * Works by first retrieving the current slug for example 'category-default.php' and then
   594  * will fallback to category.php template, if the ID category file doesn't
   720  * trying category ID, for example 'category-1.php' and will finally fallback to category.php
   595  * exist.
   721  * template, if those files don't exist.
   596  *
   722  *
   597  * @since 1.5.0
   723  * @since 1.5.0
   598  * @uses apply_filters() Calls 'category_template' on file path of category template.
   724  * @uses apply_filters() Calls 'category_template' on file path of category template.
   599  *
   725  *
   600  * @return string
   726  * @return string
   601  */
   727  */
   602 function get_category_template() {
   728 function get_category_template() {
   603 	$template = locate_template(array("category-" . absint( get_query_var('cat') ) . '.php', 'category.php'));
   729 	$cat_ID = absint( get_query_var('cat') );
       
   730 	$category = get_category( $cat_ID );
       
   731 
       
   732 	$templates = array();
       
   733 
       
   734 	if ( !is_wp_error($category) )
       
   735 		$templates[] = "category-{$category->slug}.php";
       
   736 
       
   737 	$templates[] = "category-$cat_ID.php";
       
   738 	$templates[] = "category.php";
       
   739 
       
   740 	$template = locate_template($templates);
   604 	return apply_filters('category_template', $template);
   741 	return apply_filters('category_template', $template);
   605 }
   742 }
   606 
   743 
   607 /**
   744 /**
   608  * Retrieve path of tag template in current or parent template.
   745  * Retrieve path of tag template in current or parent template.
   609  *
   746  *
   610  * Works by retrieving the current tag name, for example 'tag-wordpress.php' and will
   747  * Works by first retrieving the current tag name, for example 'tag-wordpress.php' and then
   611  * fallback to tag.php template, if the name tag file doesn't exist.
   748  * trying tag ID, for example 'tag-1.php' and will finally fallback to tag.php
       
   749  * template, if those files don't exist.
   612  *
   750  *
   613  * @since 2.3.0
   751  * @since 2.3.0
   614  * @uses apply_filters() Calls 'tag_template' on file path of tag template.
   752  * @uses apply_filters() Calls 'tag_template' on file path of tag template.
   615  *
   753  *
   616  * @return string
   754  * @return string
   617  */
   755  */
   618 function get_tag_template() {
   756 function get_tag_template() {
   619 	$template = locate_template(array("tag-" . get_query_var('tag') . '.php', 'tag.php'));
   757 	$tag_id = absint( get_query_var('tag_id') );
       
   758 	$tag_name = get_query_var('tag');
       
   759 
       
   760 	$templates = array();
       
   761 
       
   762 	if ( $tag_name )
       
   763 		$templates[] = "tag-$tag_name.php";
       
   764 	if ( $tag_id )
       
   765 		$templates[] = "tag-$tag_id.php";
       
   766 	$templates[] = "tag.php";
       
   767 
       
   768 	$template = locate_template($templates);
   620 	return apply_filters('tag_template', $template);
   769 	return apply_filters('tag_template', $template);
   621 }
   770 }
   622 
   771 
   623 /**
   772 /**
   624  * Retrieve path of taxonomy template in current or parent template.
   773  * Retrieve path of taxonomy template in current or parent template.
   680 }
   829 }
   681 
   830 
   682 /**
   831 /**
   683  * Retrieve path of page template in current or parent template.
   832  * Retrieve path of page template in current or parent template.
   684  *
   833  *
   685  * First attempt is to look for the file in the '_wp_page_template' page meta
   834  * Will first look for the specifically assigned page template
   686  * data. The second attempt, if the first has a file and is not empty, is to
   835  * The will search for 'page-{slug}.php' followed by 'page-id.php'
   687  * look for 'page.php'.
   836  * and finally 'page.php'
   688  *
   837  *
   689  * @since 1.5.0
   838  * @since 1.5.0
   690  *
   839  *
   691  * @return string
   840  * @return string
   692  */
   841  */
   693 function get_page_template() {
   842 function get_page_template() {
   694 	global $wp_query;
   843 	global $wp_query;
   695 
   844 
   696 	$id = (int) $wp_query->post->ID;
   845 	$id = (int) $wp_query->post->ID;
   697 	$template = get_post_meta($id, '_wp_page_template', true);
   846 	$template = get_post_meta($id, '_wp_page_template', true);
       
   847 	$pagename = get_query_var('pagename');
   698 
   848 
   699 	if ( 'default' == $template )
   849 	if ( 'default' == $template )
   700 		$template = '';
   850 		$template = '';
   701 
   851 
   702 	$templates = array();
   852 	$templates = array();
   703 	if ( !empty($template) && !validate_file($template) )
   853 	if ( !empty($template) && !validate_file($template) )
   704 		$templates[] = $template;
   854 		$templates[] = $template;
   705 
   855 	if ( $pagename )
       
   856 		$templates[] = "page-$pagename.php";
       
   857 	if ( $id )
       
   858 		$templates[] = "page-$id.php";
   706 	$templates[] = "page.php";
   859 	$templates[] = "page.php";
   707 
   860 
   708 	return apply_filters('page_template', locate_template($templates));
   861 	return apply_filters('page_template', locate_template($templates));
   709 }
   862 }
   710 
   863 
   859  * Start preview theme output buffer.
  1012  * Start preview theme output buffer.
   860  *
  1013  *
   861  * Will only preform task if the user has permissions and template and preview
  1014  * Will only preform task if the user has permissions and template and preview
   862  * query variables exist.
  1015  * query variables exist.
   863  *
  1016  *
   864  * @since 2.5.0
  1017  * @since 2.6.0
   865  */
  1018  */
   866 function preview_theme() {
  1019 function preview_theme() {
   867 	if ( ! (isset($_GET['template']) && isset($_GET['preview'])) )
  1020 	if ( ! (isset($_GET['template']) && isset($_GET['preview'])) )
   868 		return;
  1021 		return;
   869 
  1022 
   891 }
  1044 }
   892 add_action('setup_theme', 'preview_theme');
  1045 add_action('setup_theme', 'preview_theme');
   893 
  1046 
   894 /**
  1047 /**
   895  * Private function to modify the current template when previewing a theme
  1048  * Private function to modify the current template when previewing a theme
   896  * 
  1049  *
       
  1050  * @since 2.9.0
       
  1051  * @access private
       
  1052  *
   897  * @return string
  1053  * @return string
   898  */
  1054  */
   899 function _preview_theme_template_filter() {
  1055 function _preview_theme_template_filter() {
   900 	return isset($_GET['template']) ? $_GET['template'] : '';
  1056 	return isset($_GET['template']) ? $_GET['template'] : '';
   901 }
  1057 }
   902 
  1058 
   903 /**
  1059 /**
   904  * Private function to modify the current stylesheet when previewing a theme
  1060  * Private function to modify the current stylesheet when previewing a theme
   905  * 
  1061  *
       
  1062  * @since 2.9.0
       
  1063  * @access private
       
  1064  *
   906  * @return string
  1065  * @return string
   907  */
  1066  */
   908 function _preview_theme_stylesheet_filter() {
  1067 function _preview_theme_stylesheet_filter() {
   909 	return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : '';
  1068 	return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : '';
   910 }
  1069 }
   911 
  1070 
   912 /**
  1071 /**
   913  * Callback function for ob_start() to capture all links in the theme.
  1072  * Callback function for ob_start() to capture all links in the theme.
   914  *
  1073  *
   915  * @since unknown
  1074  * @since 2.6.0
   916  * @access private
  1075  * @access private
   917  *
  1076  *
   918  * @param string $content
  1077  * @param string $content
   919  * @return string
  1078  * @return string
   920  */
  1079  */
   925 /**
  1084 /**
   926  * Manipulates preview theme links in order to control and maintain location.
  1085  * Manipulates preview theme links in order to control and maintain location.
   927  *
  1086  *
   928  * Callback function for preg_replace_callback() to accept and filter matches.
  1087  * Callback function for preg_replace_callback() to accept and filter matches.
   929  *
  1088  *
   930  * @since unknown
  1089  * @since 2.6.0
   931  * @access private
  1090  * @access private
   932  *
  1091  *
   933  * @param array $matches
  1092  * @param array $matches
   934  * @return string
  1093  * @return string
   935  */
  1094  */
  1150 	require_once(ABSPATH . 'wp-admin/custom-header.php');
  1309 	require_once(ABSPATH . 'wp-admin/custom-header.php');
  1151 	$GLOBALS['custom_image_header'] =& new Custom_Image_Header($admin_header_callback);
  1310 	$GLOBALS['custom_image_header'] =& new Custom_Image_Header($admin_header_callback);
  1152 	add_action('admin_menu', array(&$GLOBALS['custom_image_header'], 'init'));
  1311 	add_action('admin_menu', array(&$GLOBALS['custom_image_header'], 'init'));
  1153 }
  1312 }
  1154 
  1313 
       
  1314 /**
       
  1315  * Allows a theme to register its support of a certain feature
       
  1316  * 
       
  1317  * Must be called in the themes functions.php file to work.
       
  1318  *
       
  1319  * @author Mark Jaquith
       
  1320  * @since 2.9
       
  1321  * @param string $feature the feature being added
       
  1322  */
       
  1323 function add_theme_support( $feature ) {
       
  1324 	global $_wp_theme_features;
       
  1325 
       
  1326 	if ( func_num_args() == 1 )
       
  1327 		$_wp_theme_features[$feature] = true;
       
  1328 	else
       
  1329 		$_wp_theme_features[$feature] = array_slice( func_get_args(), 1 );
       
  1330 }
       
  1331 
       
  1332 /**
       
  1333  * Checks a theme's support for a given feature
       
  1334  *
       
  1335  * @author Mark Jaquith
       
  1336  * @since 2.9
       
  1337  * @param string $feature the feature being checked
       
  1338  * @return boolean
       
  1339  */
       
  1340 
       
  1341 function current_theme_supports( $feature ) {
       
  1342 	global $_wp_theme_features;
       
  1343 
       
  1344 	if ( !isset( $_wp_theme_features[$feature] ) )
       
  1345 		return false;
       
  1346 
       
  1347 	// If no args passed then no extra checks need be performed
       
  1348 	if ( func_num_args() <= 1 )
       
  1349 		return true;
       
  1350 
       
  1351 	$args = array_slice( func_get_args(), 1 );
       
  1352 
       
  1353 	// @todo Allow pluggable arg checking
       
  1354 	switch ( $feature ) {
       
  1355 		case 'post-thumbnails':
       
  1356 			// post-thumbnails can be registered for only certain content/post types by passing
       
  1357 			// an array of types to add_theme_support().  If no array was passed, then
       
  1358 			// any type is accepted
       
  1359 			if ( true === $_wp_theme_features[$feature] )  // Registered for all types
       
  1360 				return true;
       
  1361 			$content_type = $args[0];
       
  1362 			if ( in_array($content_type, $_wp_theme_features[$feature][0]) )
       
  1363 				return true;
       
  1364 			else
       
  1365 				return false;
       
  1366 			break;
       
  1367 	}
       
  1368 
       
  1369 	return true;
       
  1370 }
       
  1371 
       
  1372 /**
       
  1373  * Checks a theme's support for a given feature before loading the functions which implement it.
       
  1374  *
       
  1375  * @author Peter Westwood
       
  1376  * @since 2.9
       
  1377  * @param string $feature the feature being checked
       
  1378  * @param string $include the file containing the functions that implement the feature
       
  1379  */
       
  1380 function require_if_theme_supports( $feature, $include) {
       
  1381 	if ( current_theme_supports( $feature ) )
       
  1382 		require ( $include );
       
  1383 }
       
  1384 
  1155 ?>
  1385 ?>