wp/wp-includes/theme.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
   135  * Retrieve name of the current stylesheet.
   135  * Retrieve name of the current stylesheet.
   136  *
   136  *
   137  * The theme name that the administrator has currently set the front end theme
   137  * The theme name that the administrator has currently set the front end theme
   138  * as.
   138  * as.
   139  *
   139  *
   140  * For all extensive purposes, the template name and the stylesheet name are
   140  * For all intents and purposes, the template name and the stylesheet name are
   141  * going to be the same for most cases.
   141  * going to be the same for most cases.
   142  *
   142  *
   143  * @since 1.5.0
   143  * @since 1.5.0
   144  * @uses apply_filters() Calls 'stylesheet' filter on stylesheet name.
       
   145  *
   144  *
   146  * @return string Stylesheet name.
   145  * @return string Stylesheet name.
   147  */
   146  */
   148 function get_stylesheet() {
   147 function get_stylesheet() {
   149 	return apply_filters('stylesheet', get_option('stylesheet'));
   148 	/**
       
   149 	 * Filter the name of current stylesheet.
       
   150 	 *
       
   151 	 * @since 1.5.0
       
   152 	 *
       
   153 	 * @param string $stylesheet Name of the current stylesheet.
       
   154 	 */
       
   155 	return apply_filters( 'stylesheet', get_option( 'stylesheet' ) );
   150 }
   156 }
   151 
   157 
   152 /**
   158 /**
   153  * Retrieve stylesheet directory path for current theme.
   159  * Retrieve stylesheet directory path for current theme.
   154  *
   160  *
   155  * @since 1.5.0
   161  * @since 1.5.0
   156  * @uses apply_filters() Calls 'stylesheet_directory' filter on stylesheet directory and theme name.
       
   157  *
   162  *
   158  * @return string Path to current theme directory.
   163  * @return string Path to current theme directory.
   159  */
   164  */
   160 function get_stylesheet_directory() {
   165 function get_stylesheet_directory() {
   161 	$stylesheet = get_stylesheet();
   166 	$stylesheet = get_stylesheet();
   162 	$theme_root = get_theme_root( $stylesheet );
   167 	$theme_root = get_theme_root( $stylesheet );
   163 	$stylesheet_dir = "$theme_root/$stylesheet";
   168 	$stylesheet_dir = "$theme_root/$stylesheet";
   164 
   169 
       
   170 	/**
       
   171 	 * Filter the stylesheet directory path for current theme.
       
   172 	 *
       
   173 	 * @since 1.5.0
       
   174 	 *
       
   175 	 * @param string $stylesheet_dir Absolute path to the current them.
       
   176 	 * @param string $stylesheet     Directory name of the current theme.
       
   177 	 * @param string $theme_root     Absolute path to themes directory.
       
   178 	 */
   165 	return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root );
   179 	return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root );
   166 }
   180 }
   167 
   181 
   168 /**
   182 /**
   169  * Retrieve stylesheet directory URI.
   183  * Retrieve stylesheet directory URI.
   171  * @since 1.5.0
   185  * @since 1.5.0
   172  *
   186  *
   173  * @return string
   187  * @return string
   174  */
   188  */
   175 function get_stylesheet_directory_uri() {
   189 function get_stylesheet_directory_uri() {
   176 	$stylesheet = get_stylesheet();
   190 	$stylesheet = str_replace( '%2F', '/', rawurlencode( get_stylesheet() ) );
   177 	$theme_root_uri = get_theme_root_uri( $stylesheet );
   191 	$theme_root_uri = get_theme_root_uri( $stylesheet );
   178 	$stylesheet_dir_uri = "$theme_root_uri/$stylesheet";
   192 	$stylesheet_dir_uri = "$theme_root_uri/$stylesheet";
   179 
   193 
       
   194 	/**
       
   195 	 * Filter the stylesheet directory URI.
       
   196 	 *
       
   197 	 * @since 1.5.0
       
   198 	 *
       
   199 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
       
   200 	 * @param string $stylesheet         Name of the activated theme's directory.
       
   201 	 * @param string $theme_root_uri     Themes root URI.
       
   202 	 */
   180 	return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri );
   203 	return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri );
   181 }
   204 }
   182 
   205 
   183 /**
   206 /**
   184  * Retrieve URI of current theme stylesheet.
   207  * Retrieve URI of current theme stylesheet.
   185  *
   208  *
   186  * The stylesheet file name is 'style.css' which is appended to {@link
   209  * The stylesheet file name is 'style.css' which is appended to {@link
   187  * get_stylesheet_directory_uri() stylesheet directory URI} path.
   210  * get_stylesheet_directory_uri() stylesheet directory URI} path.
   188  *
   211  *
   189  * @since 1.5.0
   212  * @since 1.5.0
   190  * @uses apply_filters() Calls 'stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI.
       
   191  *
   213  *
   192  * @return string
   214  * @return string
   193  */
   215  */
   194 function get_stylesheet_uri() {
   216 function get_stylesheet_uri() {
   195 	$stylesheet_dir_uri = get_stylesheet_directory_uri();
   217 	$stylesheet_dir_uri = get_stylesheet_directory_uri();
   196 	$stylesheet_uri = $stylesheet_dir_uri . '/style.css';
   218 	$stylesheet_uri = $stylesheet_dir_uri . '/style.css';
   197 	return apply_filters('stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri);
   219 	/**
       
   220 	 * Filter the URI of the current theme stylesheet.
       
   221 	 *
       
   222 	 * @since 1.5.0
       
   223 	 *
       
   224 	 * @param string $stylesheet_uri     Stylesheet URI for the current theme/child theme.
       
   225 	 * @param string $stylesheet_dir_uri Stylesheet directory URI for the current theme/child theme.
       
   226 	 */
       
   227 	return apply_filters( 'stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri );
   198 }
   228 }
   199 
   229 
   200 /**
   230 /**
   201  * Retrieve localized stylesheet URI.
   231  * Retrieve localized stylesheet URI.
   202  *
   232  *
   210  * If you want to change the location of the stylesheet files for the entire
   240  * If you want to change the location of the stylesheet files for the entire
   211  * WordPress workflow, then change the former. If you just have the locale in a
   241  * WordPress workflow, then change the former. If you just have the locale in a
   212  * separate folder, then change the latter.
   242  * separate folder, then change the latter.
   213  *
   243  *
   214  * @since 2.1.0
   244  * @since 2.1.0
   215  * @uses apply_filters() Calls 'locale_stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI.
       
   216  *
   245  *
   217  * @return string
   246  * @return string
   218  */
   247  */
   219 function get_locale_stylesheet_uri() {
   248 function get_locale_stylesheet_uri() {
   220 	global $wp_locale;
   249 	global $wp_locale;
   225 		$stylesheet_uri = "$stylesheet_dir_uri/$locale.css";
   254 		$stylesheet_uri = "$stylesheet_dir_uri/$locale.css";
   226 	elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") )
   255 	elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") )
   227 		$stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css";
   256 		$stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css";
   228 	else
   257 	else
   229 		$stylesheet_uri = '';
   258 		$stylesheet_uri = '';
   230 	return apply_filters('locale_stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri);
   259 	/**
       
   260 	 * Filter the localized stylesheet URI.
       
   261 	 *
       
   262 	 * @since 2.1.0
       
   263 	 *
       
   264 	 * @param string $stylesheet_uri     Localized stylesheet URI.
       
   265 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
       
   266 	 */
       
   267 	return apply_filters( 'locale_stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri );
   231 }
   268 }
   232 
   269 
   233 /**
   270 /**
   234  * Retrieve name of the current theme.
   271  * Retrieve name of the current theme.
   235  *
   272  *
   236  * @since 1.5.0
   273  * @since 1.5.0
   237  * @uses apply_filters() Calls 'template' filter on template option.
       
   238  *
   274  *
   239  * @return string Template name.
   275  * @return string Template name.
   240  */
   276  */
   241 function get_template() {
   277 function get_template() {
   242 	return apply_filters('template', get_option('template'));
   278 	/**
       
   279 	 * Filter the name of the current theme.
       
   280 	 *
       
   281 	 * @since 1.5.0
       
   282 	 *
       
   283 	 * @param string $template Current theme's directory name.
       
   284 	 */
       
   285 	return apply_filters( 'template', get_option( 'template' ) );
   243 }
   286 }
   244 
   287 
   245 /**
   288 /**
   246  * Retrieve current theme directory.
   289  * Retrieve current theme directory.
   247  *
   290  *
   248  * @since 1.5.0
   291  * @since 1.5.0
   249  * @uses apply_filters() Calls 'template_directory' filter on template directory path and template name.
       
   250  *
   292  *
   251  * @return string Template directory path.
   293  * @return string Template directory path.
   252  */
   294  */
   253 function get_template_directory() {
   295 function get_template_directory() {
   254 	$template = get_template();
   296 	$template = get_template();
   255 	$theme_root = get_theme_root( $template );
   297 	$theme_root = get_theme_root( $template );
   256 	$template_dir = "$theme_root/$template";
   298 	$template_dir = "$theme_root/$template";
   257 
   299 
       
   300 	/**
       
   301 	 * Filter the current theme directory path.
       
   302 	 *
       
   303 	 * @since 1.5.0
       
   304 	 *
       
   305 	 * @param string $template_dir The URI of the current theme directory.
       
   306 	 * @param string $template     Directory name of the current theme.
       
   307 	 * @param string $theme_root   Absolute path to the themes directory.
       
   308 	 */
   258 	return apply_filters( 'template_directory', $template_dir, $template, $theme_root );
   309 	return apply_filters( 'template_directory', $template_dir, $template, $theme_root );
   259 }
   310 }
   260 
   311 
   261 /**
   312 /**
   262  * Retrieve theme directory URI.
   313  * Retrieve theme directory URI.
   263  *
   314  *
   264  * @since 1.5.0
   315  * @since 1.5.0
   265  * @uses apply_filters() Calls 'template_directory_uri' filter on template directory URI path and template name.
       
   266  *
   316  *
   267  * @return string Template directory URI.
   317  * @return string Template directory URI.
   268  */
   318  */
   269 function get_template_directory_uri() {
   319 function get_template_directory_uri() {
   270 	$template = get_template();
   320 	$template = str_replace( '%2F', '/', rawurlencode( get_template() ) );
   271 	$theme_root_uri = get_theme_root_uri( $template );
   321 	$theme_root_uri = get_theme_root_uri( $template );
   272 	$template_dir_uri = "$theme_root_uri/$template";
   322 	$template_dir_uri = "$theme_root_uri/$template";
   273 
   323 
       
   324 	/**
       
   325 	 * Filter the current theme directory URI.
       
   326 	 *
       
   327 	 * @since 1.5.0
       
   328 	 *
       
   329 	 * @param string $template_dir_uri The URI of the current theme directory.
       
   330 	 * @param string $template         Directory name of the current theme.
       
   331 	 * @param string $theme_root_uri   The themes root URI.
       
   332 	 */
   274 	return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri );
   333 	return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri );
   275 }
   334 }
   276 
   335 
   277 /**
   336 /**
   278  * Retrieve theme roots.
   337  * Retrieve theme roots.
   308 
   367 
   309 	if ( ! file_exists( $directory ) ) {
   368 	if ( ! file_exists( $directory ) ) {
   310 		// Try prepending as the theme directory could be relative to the content directory
   369 		// Try prepending as the theme directory could be relative to the content directory
   311 		$directory = WP_CONTENT_DIR . '/' . $directory;
   370 		$directory = WP_CONTENT_DIR . '/' . $directory;
   312 		// If this directory does not exist, return and do not register
   371 		// If this directory does not exist, return and do not register
   313 		if ( ! file_exists( $directory ) )
   372 		if ( ! file_exists( $directory ) ) {
   314 			return false;
   373 			return false;
   315 	}
   374 		}
   316 
   375 	}
   317 	$wp_theme_directories[] = $directory;
   376 
       
   377 	if ( ! is_array( $wp_theme_directories ) ) {
       
   378 		$wp_theme_directories = array();
       
   379 	}
       
   380 
       
   381 	$untrailed = untrailingslashit( $directory );
       
   382 	if ( ! empty( $untrailed ) && ! in_array( $untrailed, $wp_theme_directories ) ) {
       
   383 		$wp_theme_directories[] = $untrailed;
       
   384 	}
   318 
   385 
   319 	return true;
   386 	return true;
   320 }
   387 }
   321 
   388 
   322 /**
   389 /**
   337 		return $found_themes;
   404 		return $found_themes;
   338 
   405 
   339 	$found_themes = array();
   406 	$found_themes = array();
   340 
   407 
   341 	$wp_theme_directories = (array) $wp_theme_directories;
   408 	$wp_theme_directories = (array) $wp_theme_directories;
       
   409 	$relative_theme_roots = array();
   342 
   410 
   343 	// Set up maybe-relative, maybe-absolute array of theme directories.
   411 	// Set up maybe-relative, maybe-absolute array of theme directories.
   344 	// We always want to return absolute, but we need to cache relative
   412 	// We always want to return absolute, but we need to cache relative
   345 	// to use in get_theme_root().
   413 	// to use in get_theme_root().
   346 	foreach ( $wp_theme_directories as $theme_root ) {
   414 	foreach ( $wp_theme_directories as $theme_root ) {
   348 			$relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root;
   416 			$relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root;
   349 		else
   417 		else
   350 			$relative_theme_roots[ $theme_root ] = $theme_root;
   418 			$relative_theme_roots[ $theme_root ] = $theme_root;
   351 	}
   419 	}
   352 
   420 
       
   421 	/**
       
   422 	 * Filter whether to get the cache of the registered theme directories.
       
   423 	 *
       
   424 	 * @since 3.4.0
       
   425 	 *
       
   426 	 * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
       
   427 	 * @param string $cache_directory  Directory to be searched for the cache.
       
   428 	 */
   353 	if ( $cache_expiration = apply_filters( 'wp_cache_themes_persistently', false, 'search_theme_directories' ) ) {
   429 	if ( $cache_expiration = apply_filters( 'wp_cache_themes_persistently', false, 'search_theme_directories' ) ) {
   354 		$cached_roots = get_site_transient( 'theme_roots' );
   430 		$cached_roots = get_site_transient( 'theme_roots' );
   355 		if ( is_array( $cached_roots ) ) {
   431 		if ( is_array( $cached_roots ) ) {
   356 			foreach ( $cached_roots as $theme_dir => $theme_root ) {
   432 			foreach ( $cached_roots as $theme_dir => $theme_root ) {
   357 				// A cached theme root is no longer around, so skip it.
   433 				// A cached theme root is no longer around, so skip it.
   439  * Retrieve path to themes directory.
   515  * Retrieve path to themes directory.
   440  *
   516  *
   441  * Does not have trailing slash.
   517  * Does not have trailing slash.
   442  *
   518  *
   443  * @since 1.5.0
   519  * @since 1.5.0
   444  * @uses apply_filters() Calls 'theme_root' filter on path.
       
   445  *
   520  *
   446  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   521  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   447  * @return string Theme path.
   522  * @return string Theme path.
   448  */
   523  */
   449 function get_theme_root( $stylesheet_or_template = false ) {
   524 function get_theme_root( $stylesheet_or_template = false ) {
   456 			$theme_root = WP_CONTENT_DIR . $theme_root;
   531 			$theme_root = WP_CONTENT_DIR . $theme_root;
   457 	} else {
   532 	} else {
   458 		$theme_root = WP_CONTENT_DIR . '/themes';
   533 		$theme_root = WP_CONTENT_DIR . '/themes';
   459 	}
   534 	}
   460 
   535 
       
   536 	/**
       
   537 	 * Filter the absolute path to the themes directory.
       
   538 	 *
       
   539 	 * @since 1.5.0
       
   540 	 *
       
   541 	 * @param string $theme_root Absolute path to themes directory.
       
   542 	 */
   461 	return apply_filters( 'theme_root', $theme_root );
   543 	return apply_filters( 'theme_root', $theme_root );
   462 }
   544 }
   463 
   545 
   464 /**
   546 /**
   465  * Retrieve URI for themes directory.
   547  * Retrieve URI for themes directory.
   496 		}
   578 		}
   497 	} else {
   579 	} else {
   498 		$theme_root_uri = content_url( 'themes' );
   580 		$theme_root_uri = content_url( 'themes' );
   499 	}
   581 	}
   500 
   582 
   501 	return apply_filters( 'theme_root_uri', $theme_root_uri, get_option('siteurl'), $stylesheet_or_template );
   583 	/**
       
   584 	 * Filter the URI for themes directory.
       
   585 	 *
       
   586 	 * @since 1.5.0
       
   587 	 *
       
   588 	 * @param string $theme_root_uri         The URI for themes directory.
       
   589 	 * @param string $siteurl                WordPress web address which is set in General Options.
       
   590 	 * @param string $stylesheet_or_template Stylesheet or template name of the theme.
       
   591 	 */
       
   592 	return apply_filters( 'theme_root_uri', $theme_root_uri, get_option( 'siteurl' ), $stylesheet_or_template );
   502 }
   593 }
   503 
   594 
   504 /**
   595 /**
   505  * Get the raw theme root relative to the content directory with no filters applied.
   596  * Get the raw theme root relative to the content directory with no filters applied.
   506  *
   597  *
   583 	// Prevent theme mods to current theme being used on theme being previewed
   674 	// Prevent theme mods to current theme being used on theme being previewed
   584 	add_filter( 'pre_option_theme_mods_' . get_option( 'stylesheet' ), '__return_empty_array' );
   675 	add_filter( 'pre_option_theme_mods_' . get_option( 'stylesheet' ), '__return_empty_array' );
   585 
   676 
   586 	ob_start( 'preview_theme_ob_filter' );
   677 	ob_start( 'preview_theme_ob_filter' );
   587 }
   678 }
   588 add_action('setup_theme', 'preview_theme');
       
   589 
   679 
   590 /**
   680 /**
   591  * Private function to modify the current template when previewing a theme
   681  * Private function to modify the current template when previewing a theme
   592  *
   682  *
   593  * @since 2.9.0
   683  * @since 2.9.0
   663  *
   753  *
   664  * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature
   754  * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature
   665  * of two arguments: $template then $stylesheet. This is for backwards compatibility.
   755  * of two arguments: $template then $stylesheet. This is for backwards compatibility.
   666  *
   756  *
   667  * @since 2.5.0
   757  * @since 2.5.0
   668  * @uses do_action() Calls 'switch_theme' action, passing the new theme.
       
   669  *
   758  *
   670  * @param string $stylesheet Stylesheet name
   759  * @param string $stylesheet Stylesheet name
   671  */
   760  */
   672 function switch_theme( $stylesheet ) {
   761 function switch_theme( $stylesheet ) {
   673 	global $wp_theme_directories, $sidebars_widgets;
   762 	global $wp_theme_directories, $wp_customize, $sidebars_widgets;
   674 
   763 
   675 	if ( is_array( $sidebars_widgets ) )
   764 	$_sidebars_widgets = null;
   676 		set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $sidebars_widgets ) );
   765 	if ( 'wp_ajax_customize_save' === current_action() ) {
       
   766 		$_sidebars_widgets = $wp_customize->post_value( $wp_customize->get_setting( 'old_sidebars_widgets_data' ) );
       
   767 	} elseif ( is_array( $sidebars_widgets ) ) {
       
   768 		$_sidebars_widgets = $sidebars_widgets;
       
   769 	}
       
   770 
       
   771 	if ( is_array( $_sidebars_widgets ) ) {
       
   772 		set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $_sidebars_widgets ) );
       
   773 	}
   677 
   774 
   678 	$old_theme  = wp_get_theme();
   775 	$old_theme  = wp_get_theme();
   679 	$new_theme = wp_get_theme( $stylesheet );
   776 	$new_theme = wp_get_theme( $stylesheet );
   680 
   777 
   681 	if ( func_num_args() > 1 ) {
   778 	if ( func_num_args() > 1 ) {
   698 
   795 
   699 	$new_name  = $new_theme->get('Name');
   796 	$new_name  = $new_theme->get('Name');
   700 
   797 
   701 	update_option( 'current_theme', $new_name );
   798 	update_option( 'current_theme', $new_name );
   702 
   799 
       
   800 	// Migrate from the old mods_{name} option to theme_mods_{slug}.
   703 	if ( is_admin() && false === get_option( 'theme_mods_' . $stylesheet ) ) {
   801 	if ( is_admin() && false === get_option( 'theme_mods_' . $stylesheet ) ) {
   704 		$default_theme_mods = (array) get_option( 'mods_' . $new_name );
   802 		$default_theme_mods = (array) get_option( 'mods_' . $new_name );
   705 		add_option( "theme_mods_$stylesheet", $default_theme_mods );
   803 		add_option( "theme_mods_$stylesheet", $default_theme_mods );
       
   804 	} else {
       
   805 		/*
       
   806 		 * Since retrieve_widgets() is called when initializing a theme in the Customizer,
       
   807 		 * we need to to remove the theme mods to avoid overwriting changes made via
       
   808 		 * the Customizer when accessing wp-admin/widgets.php.
       
   809 		 */
       
   810 		if ( 'wp_ajax_customize_save' === current_action() ) {
       
   811 			remove_theme_mod( 'sidebars_widgets' );
       
   812 		}
   706 	}
   813 	}
   707 
   814 
   708 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
   815 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
       
   816 	/**
       
   817 	 * Fires after the theme is switched.
       
   818 	 *
       
   819 	 * @since 1.5.0
       
   820 	 *
       
   821 	 * @param string   $new_name  Name of the new theme.
       
   822 	 * @param WP_Theme $new_theme WP_Theme instance of the new theme.
       
   823 	 */
   709 	do_action( 'switch_theme', $new_name, $new_theme );
   824 	do_action( 'switch_theme', $new_name, $new_theme );
   710 }
   825 }
   711 
   826 
   712 /**
   827 /**
   713  * Checks that current theme files 'index.php' and 'style.css' exists.
   828  * Checks that current theme files 'index.php' and 'style.css' exists.
   721  * @see WP_DEFAULT_THEME
   836  * @see WP_DEFAULT_THEME
   722  *
   837  *
   723  * @return bool
   838  * @return bool
   724  */
   839  */
   725 function validate_current_theme() {
   840 function validate_current_theme() {
   726 	// Don't validate during an install/upgrade.
   841 	/**
   727 	if ( defined('WP_INSTALLING') || !apply_filters( 'validate_current_theme', true ) )
   842 	 * Filter whether to validate the current theme.
       
   843 	 *
       
   844 	 * @since 2.7.0
       
   845 	 *
       
   846 	 * @param bool true Validation flag to check the current theme.
       
   847 	 */
       
   848 	if ( defined('WP_INSTALLING') || ! apply_filters( 'validate_current_theme', true ) )
   728 		return true;
   849 		return true;
   729 
   850 
   730 	if ( get_template() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/index.php') ) {
   851 	if ( get_template() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/index.php') ) {
   731 		switch_theme( WP_DEFAULT_THEME );
   852 		switch_theme( WP_DEFAULT_THEME );
   732 		return false;
   853 		return false;
   748 /**
   869 /**
   749  * Retrieve all theme modifications.
   870  * Retrieve all theme modifications.
   750  *
   871  *
   751  * @since 3.1.0
   872  * @since 3.1.0
   752  *
   873  *
   753  * @return array Theme modifications.
   874  * @return array|null Theme modifications.
   754  */
   875  */
   755 function get_theme_mods() {
   876 function get_theme_mods() {
   756 	$theme_slug = get_option( 'stylesheet' );
   877 	$theme_slug = get_option( 'stylesheet' );
   757 	if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) {
   878 	if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) {
   758 		$theme_name = get_option( 'current_theme' );
   879 		$theme_name = get_option( 'current_theme' );
   774  * through {@link http://php.net/sprintf sprintf()} PHP function with the first
   895  * through {@link http://php.net/sprintf sprintf()} PHP function with the first
   775  * string the template directory URI and the second string the stylesheet
   896  * string the template directory URI and the second string the stylesheet
   776  * directory URI.
   897  * directory URI.
   777  *
   898  *
   778  * @since 2.1.0
   899  * @since 2.1.0
   779  * @uses apply_filters() Calls 'theme_mod_$name' filter on the value.
       
   780  *
   900  *
   781  * @param string $name Theme modification name.
   901  * @param string $name Theme modification name.
   782  * @param bool|string $default
   902  * @param bool|string $default
   783  * @return string
   903  * @return string
   784  */
   904  */
   785 function get_theme_mod( $name, $default = false ) {
   905 function get_theme_mod( $name, $default = false ) {
   786 	$mods = get_theme_mods();
   906 	$mods = get_theme_mods();
   787 
   907 
   788 	if ( isset( $mods[ $name ] ) )
   908 	if ( isset( $mods[$name] ) ) {
   789 		return apply_filters( "theme_mod_$name", $mods[ $name ] );
   909 		/**
       
   910 		 * Filter the theme modification, or 'theme_mod', value.
       
   911 		 *
       
   912 		 * The dynamic portion of the hook name, `$name`, refers to
       
   913 		 * the key name of the modification array. For example,
       
   914 		 * 'header_textcolor', 'header_image', and so on depending
       
   915 		 * on the theme options.
       
   916 		 *
       
   917 		 * @since 2.2.0
       
   918 		 *
       
   919 		 * @param string $current_mod The value of the current theme modification.
       
   920 		 */
       
   921 		return apply_filters( "theme_mod_{$name}", $mods[$name] );
       
   922 	}
   790 
   923 
   791 	if ( is_string( $default ) )
   924 	if ( is_string( $default ) )
   792 		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
   925 		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
   793 
   926 
   794 	return apply_filters( "theme_mod_$name", $default );
   927 	/** This filter is documented in wp-includes/theme.php */
       
   928 	return apply_filters( "theme_mod_{$name}", $default );
   795 }
   929 }
   796 
   930 
   797 /**
   931 /**
   798  * Update theme modification value for the current theme.
   932  * Update theme modification value for the current theme.
   799  *
   933  *
   800  * @since 2.1.0
   934  * @since 2.1.0
   801  *
   935  *
   802  * @param string $name Theme modification name.
   936  * @param string $name Theme modification name.
   803  * @param string $value theme modification value.
   937  * @param mixed  $value theme modification value.
   804  */
   938  */
   805 function set_theme_mod( $name, $value ) {
   939 function set_theme_mod( $name, $value ) {
   806 	$mods = get_theme_mods();
   940 	$mods = get_theme_mods();
   807 
   941 	$old_value = isset( $mods[ $name ] ) ? $mods[ $name ] : false;
   808 	$mods[ $name ] = $value;
   942 
       
   943 	/**
       
   944 	 * Filter the theme mod value on save.
       
   945 	 *
       
   946 	 * The dynamic portion of the hook name, `$name`, refers to the key name of
       
   947 	 * the modification array. For example, 'header_textcolor', 'header_image',
       
   948 	 * and so on depending on the theme options.
       
   949 	 *
       
   950 	 * @since 3.9.0
       
   951 	 *
       
   952 	 * @param string $value     The new value of the theme mod.
       
   953 	 * @param string $old_value The current value of the theme mod.
       
   954 	 */
       
   955 	$mods[ $name ] = apply_filters( "pre_set_theme_mod_$name", $value, $old_value );
   809 
   956 
   810 	$theme = get_option( 'stylesheet' );
   957 	$theme = get_option( 'stylesheet' );
   811 	update_option( "theme_mods_$theme", $mods );
   958 	update_option( "theme_mods_$theme", $mods );
   812 }
   959 }
   813 
   960 
   886 	$text_color = get_theme_mod( 'header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
  1033 	$text_color = get_theme_mod( 'header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
   887 	return 'blank' != $text_color;
  1034 	return 'blank' != $text_color;
   888 }
  1035 }
   889 
  1036 
   890 /**
  1037 /**
       
  1038  * Check whether a header image is set or not.
       
  1039  *
       
  1040  * @since 4.2.0
       
  1041  *
       
  1042  * @see get_header_image()
       
  1043  *
       
  1044  * @return bool Whether a header image is set or not.
       
  1045  */
       
  1046 function has_header_image() {
       
  1047 	return (bool) get_header_image();
       
  1048 }
       
  1049 
       
  1050 /**
   891  * Retrieve header image for custom header.
  1051  * Retrieve header image for custom header.
   892  *
  1052  *
   893  * @since 2.1.0
  1053  * @since 2.1.0
   894  *
  1054  *
   895  * @return string
  1055  * @return string|false
   896  */
  1056  */
   897 function get_header_image() {
  1057 function get_header_image() {
   898 	$url = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
  1058 	$url = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
   899 
  1059 
   900 	if ( 'remove-header' == $url )
  1060 	if ( 'remove-header' == $url )
   993  * Display header image URL.
  1153  * Display header image URL.
   994  *
  1154  *
   995  * @since 2.1.0
  1155  * @since 2.1.0
   996  */
  1156  */
   997 function header_image() {
  1157 function header_image() {
   998 	echo esc_url( get_header_image() );
  1158 	$image = get_header_image();
       
  1159 	if ( $image ) {
       
  1160 		echo esc_url( $image );
       
  1161 	}
   999 }
  1162 }
  1000 
  1163 
  1001 /**
  1164 /**
  1002  * Get the header images uploaded for the current theme.
  1165  * Get the header images uploaded for the current theme.
  1003  *
  1166  *
  1013 
  1176 
  1014 	if ( empty( $headers ) )
  1177 	if ( empty( $headers ) )
  1015 		return array();
  1178 		return array();
  1016 
  1179 
  1017 	foreach ( (array) $headers as $header ) {
  1180 	foreach ( (array) $headers as $header ) {
  1018 		$url = esc_url_raw( $header->guid );
  1181 		$url = esc_url_raw( wp_get_attachment_url( $header->ID ) );
  1019 		$header_data = wp_get_attachment_metadata( $header->ID );
  1182 		$header_data = wp_get_attachment_metadata( $header->ID );
  1020 		$header_index = basename($url);
  1183 		$header_index = basename($url);
  1021 		$header_images[$header_index] = array();
  1184 		$header_images[$header_index] = array();
  1022 		$header_images[$header_index]['attachment_id'] =  $header->ID;
  1185 		$header_images[$header_index]['attachment_id'] =  $header->ID;
  1023 		$header_images[$header_index]['url'] =  $url;
  1186 		$header_images[$header_index]['url'] =  $url;
  1093  *
  1256  *
  1094  * @see register_default_headers()
  1257  * @see register_default_headers()
  1095  * @since 3.0.0
  1258  * @since 3.0.0
  1096  *
  1259  *
  1097  * @param string|array $header The header string id (key of array) to remove, or an array thereof.
  1260  * @param string|array $header The header string id (key of array) to remove, or an array thereof.
  1098  * @return True on success, false on failure.
  1261  * @return bool|void A single header returns true on success, false on failure.
       
  1262  *                   There is currently no return value for multiple headers.
  1099  */
  1263  */
  1100 function unregister_default_headers( $header ) {
  1264 function unregister_default_headers( $header ) {
  1101 	global $_wp_default_headers;
  1265 	global $_wp_default_headers;
  1102 	if ( is_array( $header ) ) {
  1266 	if ( is_array( $header ) ) {
  1103 		array_map( 'unregister_default_headers', $header );
  1267 		array_map( 'unregister_default_headers', $header );
  1159 	// $background is the saved custom image, or the default image.
  1323 	// $background is the saved custom image, or the default image.
  1160 	$background = set_url_scheme( get_background_image() );
  1324 	$background = set_url_scheme( get_background_image() );
  1161 
  1325 
  1162 	// $color is the saved custom color.
  1326 	// $color is the saved custom color.
  1163 	// A default has to be specified in style.css. It will not be printed here.
  1327 	// A default has to be specified in style.css. It will not be printed here.
  1164 	$color = get_theme_mod( 'background_color' );
  1328 	$color = get_background_color();
       
  1329 
       
  1330 	if ( $color === get_theme_support( 'custom-background', 'default-color' ) ) {
       
  1331 		$color = false;
       
  1332 	}
  1165 
  1333 
  1166 	if ( ! $background && ! $color )
  1334 	if ( ! $background && ! $color )
  1167 		return;
  1335 		return;
  1168 
  1336 
  1169 	$style = $color ? "background-color: #$color;" : '';
  1337 	$style = $color ? "background-color: #$color;" : '';
  1170 
  1338 
  1171 	if ( $background ) {
  1339 	if ( $background ) {
  1172 		$image = " background-image: url('$background');";
  1340 		$image = " background-image: url('$background');";
  1173 
  1341 
  1174 		$repeat = get_theme_mod( 'background_repeat', 'repeat' );
  1342 		$repeat = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) );
  1175 		if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
  1343 		if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
  1176 			$repeat = 'repeat';
  1344 			$repeat = 'repeat';
  1177 		$repeat = " background-repeat: $repeat;";
  1345 		$repeat = " background-repeat: $repeat;";
  1178 
  1346 
  1179 		$position = get_theme_mod( 'background_position_x', 'left' );
  1347 		$position = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
  1180 		if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) )
  1348 		if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) )
  1181 			$position = 'left';
  1349 			$position = 'left';
  1182 		$position = " background-position: top $position;";
  1350 		$position = " background-position: top $position;";
  1183 
  1351 
  1184 		$attachment = get_theme_mod( 'background_attachment', 'scroll' );
  1352 		$attachment = get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) );
  1185 		if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) )
  1353 		if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) )
  1186 			$attachment = 'scroll';
  1354 			$attachment = 'scroll';
  1187 		$attachment = " background-attachment: $attachment;";
  1355 		$attachment = " background-attachment: $attachment;";
  1188 
  1356 
  1189 		$style .= $image . $repeat . $position . $attachment;
  1357 		$style .= $image . $repeat . $position . $attachment;
  1210  * Since version 3.4 the TinyMCE body has .rtl CSS class.
  1378  * Since version 3.4 the TinyMCE body has .rtl CSS class.
  1211  * It is a better option to use that class and add any RTL styles to the main stylesheet.
  1379  * It is a better option to use that class and add any RTL styles to the main stylesheet.
  1212  *
  1380  *
  1213  * @since 3.0.0
  1381  * @since 3.0.0
  1214  *
  1382  *
  1215  * @param mixed $stylesheet Optional. Stylesheet name or array thereof, relative to theme root.
  1383  * @param array|string $stylesheet Optional. Stylesheet name or array thereof, relative to theme root.
  1216  * 	Defaults to 'editor-style.css'
  1384  * 	Defaults to 'editor-style.css'
  1217  */
  1385  */
  1218 function add_editor_style( $stylesheet = 'editor-style.css' ) {
  1386 function add_editor_style( $stylesheet = 'editor-style.css' ) {
  1219 
  1387 
  1220 	add_theme_support( 'editor-style' );
  1388 	add_theme_support( 'editor-style' );
  1248 		$GLOBALS['editor_styles'] = array();
  1416 		$GLOBALS['editor_styles'] = array();
  1249 	return true;
  1417 	return true;
  1250 }
  1418 }
  1251 
  1419 
  1252 /**
  1420 /**
       
  1421  * Retrieve any registered editor stylesheets
       
  1422  *
       
  1423  * @since 4.0.0
       
  1424  *
       
  1425  * @global $editor_styles Registered editor stylesheets
       
  1426  *
       
  1427  * @return array If registered, a list of editor stylesheet URLs.
       
  1428  */
       
  1429 function get_editor_stylesheets() {
       
  1430 	$stylesheets = array();
       
  1431 	// load editor_style.css if the current theme supports it
       
  1432 	if ( ! empty( $GLOBALS['editor_styles'] ) && is_array( $GLOBALS['editor_styles'] ) ) {
       
  1433 		$editor_styles = $GLOBALS['editor_styles'];
       
  1434 
       
  1435 		$editor_styles = array_unique( array_filter( $editor_styles ) );
       
  1436 		$style_uri = get_stylesheet_directory_uri();
       
  1437 		$style_dir = get_stylesheet_directory();
       
  1438 
       
  1439 		// Support externally referenced styles (like, say, fonts).
       
  1440 		foreach ( $editor_styles as $key => $file ) {
       
  1441 			if ( preg_match( '~^(https?:)?//~', $file ) ) {
       
  1442 				$stylesheets[] = esc_url_raw( $file );
       
  1443 				unset( $editor_styles[ $key ] );
       
  1444 			}
       
  1445 		}
       
  1446 
       
  1447 		// Look in a parent theme first, that way child theme CSS overrides.
       
  1448 		if ( is_child_theme() ) {
       
  1449 			$template_uri = get_template_directory_uri();
       
  1450 			$template_dir = get_template_directory();
       
  1451 
       
  1452 			foreach ( $editor_styles as $key => $file ) {
       
  1453 				if ( $file && file_exists( "$template_dir/$file" ) ) {
       
  1454 					$stylesheets[] = "$template_uri/$file";
       
  1455 				}
       
  1456 			}
       
  1457 		}
       
  1458 
       
  1459 		foreach ( $editor_styles as $file ) {
       
  1460 			if ( $file && file_exists( "$style_dir/$file" ) ) {
       
  1461 				$stylesheets[] = "$style_uri/$file";
       
  1462 			}
       
  1463 		}
       
  1464 	}
       
  1465 	return $stylesheets;
       
  1466 }
       
  1467 
       
  1468 /**
  1253  * Allows a theme to register its support of a certain feature
  1469  * Allows a theme to register its support of a certain feature
  1254  *
  1470  *
  1255  * Must be called in the theme's functions.php file to work.
  1471  * Must be called in the theme's functions.php file to work.
  1256  * If attached to a hook, it must be after_setup_theme.
  1472  * If attached to a hook, it must be after_setup_theme.
  1257  * The init hook may be too late for some features.
  1473  * The init hook may be too late for some features.
  1258  *
  1474  *
  1259  * @since 2.9.0
  1475  * @since 2.9.0
  1260  * @param string $feature the feature being added
  1476  *
       
  1477  * @param string $feature The feature being added.
       
  1478  * @return void|bool False on failure, void otherwise.
  1261  */
  1479  */
  1262 function add_theme_support( $feature ) {
  1480 function add_theme_support( $feature ) {
  1263 	global $_wp_theme_features;
  1481 	global $_wp_theme_features;
  1264 
  1482 
  1265 	if ( func_num_args() == 1 )
  1483 	if ( func_num_args() == 1 )
  1267 	else
  1485 	else
  1268 		$args = array_slice( func_get_args(), 1 );
  1486 		$args = array_slice( func_get_args(), 1 );
  1269 
  1487 
  1270 	switch ( $feature ) {
  1488 	switch ( $feature ) {
  1271 		case 'post-formats' :
  1489 		case 'post-formats' :
  1272 			if ( is_array( $args[0] ) )
  1490 			if ( is_array( $args[0] ) ) {
  1273 				$args[0] = array_intersect( $args[0], array_keys( get_post_format_slugs() ) );
  1491 				$post_formats = get_post_format_slugs();
       
  1492 				unset( $post_formats['standard'] );
       
  1493 
       
  1494 				$args[0] = array_intersect( $args[0], array_keys( $post_formats ) );
       
  1495 			}
  1274 			break;
  1496 			break;
  1275 
  1497 
  1276 		case 'html5' :
  1498 		case 'html5' :
  1277 			// You can't just pass 'html5', you need to pass an array of types.
  1499 			// You can't just pass 'html5', you need to pass an array of types.
  1278 			if ( empty( $args[0] ) ) {
  1500 			if ( empty( $args[0] ) ) {
       
  1501 				// Build an array of types for back-compat.
  1279 				$args = array( 0 => array( 'comment-list', 'comment-form', 'search-form' ) );
  1502 				$args = array( 0 => array( 'comment-list', 'comment-form', 'search-form' ) );
  1280 			} elseif ( ! is_array( $args[0] ) ) {
  1503 			} elseif ( ! is_array( $args[0] ) ) {
  1281 				_doing_it_wrong( "add_theme_support( 'html5' )", 'You need to pass an array of types.', '3.6.1' );
  1504 				_doing_it_wrong( "add_theme_support( 'html5' )", __( 'You need to pass an array of types.' ), '3.6.1' );
  1282 				return false;
  1505 				return false;
  1283 			}
  1506 			}
  1284 
  1507 
  1285 			// Calling 'html5' again merges, rather than overwrites.
  1508 			// Calling 'html5' again merges, rather than overwrites.
  1286 			if ( isset( $_wp_theme_features['html5'] ) )
  1509 			if ( isset( $_wp_theme_features['html5'] ) )
  1287 				$args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] );
  1510 				$args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] );
  1288 			break;
  1511 			break;
  1289 
  1512 
  1290 		case 'custom-header-uploads' :
  1513 		case 'custom-header-uploads' :
  1291 			return add_theme_support( 'custom-header', array( 'uploads' => true ) );
  1514 			return add_theme_support( 'custom-header', array( 'uploads' => true ) );
  1292 			break;
       
  1293 
  1515 
  1294 		case 'custom-header' :
  1516 		case 'custom-header' :
  1295 			if ( ! is_array( $args ) )
  1517 			if ( ! is_array( $args ) )
  1296 				$args = array( 0 => array() );
  1518 				$args = array( 0 => array() );
  1297 
  1519 
  1371 		case 'custom-background' :
  1593 		case 'custom-background' :
  1372 			if ( ! is_array( $args ) )
  1594 			if ( ! is_array( $args ) )
  1373 				$args = array( 0 => array() );
  1595 				$args = array( 0 => array() );
  1374 
  1596 
  1375 			$defaults = array(
  1597 			$defaults = array(
  1376 				'default-image' => '',
  1598 				'default-image'          => '',
  1377 				'default-color' => '',
  1599 				'default-repeat'         => 'repeat',
  1378 				'wp-head-callback' => '_custom_background_cb',
  1600 				'default-position-x'     => 'left',
  1379 				'admin-head-callback' => '',
  1601 				'default-attachment'     => 'scroll',
       
  1602 				'default-color'          => '',
       
  1603 				'wp-head-callback'       => '_custom_background_cb',
       
  1604 				'admin-head-callback'    => '',
  1380 				'admin-preview-callback' => '',
  1605 				'admin-preview-callback' => '',
  1381 			);
  1606 			);
  1382 
  1607 
  1383 			$jit = isset( $args[0]['__jit'] );
  1608 			$jit = isset( $args[0]['__jit'] );
  1384 			unset( $args[0]['__jit'] );
  1609 			unset( $args[0]['__jit'] );
  1399 				$args[0]['default-image'] = BACKGROUND_IMAGE;
  1624 				$args[0]['default-image'] = BACKGROUND_IMAGE;
  1400 			elseif ( isset( $args[0]['default-image'] ) || $jit )
  1625 			elseif ( isset( $args[0]['default-image'] ) || $jit )
  1401 				define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
  1626 				define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
  1402 
  1627 
  1403 			break;
  1628 			break;
       
  1629 
       
  1630 		// Ensure that 'title-tag' is accessible in the admin.
       
  1631 		case 'title-tag' :
       
  1632 			// Can be called in functions.php but must happen before wp_loaded, i.e. not in header.php.
       
  1633 			if ( did_action( 'wp_loaded' ) ) {
       
  1634 				/* translators: 1: Theme support 2: hook name */
       
  1635 				_doing_it_wrong( "add_theme_support( 'title-tag' )", sprintf( __( 'Theme support for %1$s should be registered before the %2$s hook.' ),
       
  1636 					'<code>title-tag</code>', '<code>wp_loaded</code>' ), '4.1' );
       
  1637 
       
  1638 				return false;
       
  1639 			}
  1404 	}
  1640 	}
  1405 
  1641 
  1406 	$_wp_theme_features[ $feature ] = $args;
  1642 	$_wp_theme_features[ $feature ] = $args;
  1407 }
  1643 }
  1408 
  1644 
  1440 			require_once( ABSPATH . 'wp-admin/custom-background.php' );
  1676 			require_once( ABSPATH . 'wp-admin/custom-background.php' );
  1441 			$custom_background = new Custom_Background( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] );
  1677 			$custom_background = new Custom_Background( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] );
  1442 		}
  1678 		}
  1443 	}
  1679 	}
  1444 }
  1680 }
  1445 add_action( 'wp_loaded', '_custom_header_background_just_in_time' );
       
  1446 
  1681 
  1447 /**
  1682 /**
  1448  * Gets the theme support arguments passed when registering that support
  1683  * Gets the theme support arguments passed when registering that support
  1449  *
  1684  *
  1450  * @since 3.1
  1685  * @since 3.1.0
       
  1686  *
  1451  * @param string $feature the feature to check
  1687  * @param string $feature the feature to check
  1452  * @return array The array of extra arguments
  1688  * @return mixed The array of extra arguments or the value for the registered feature.
  1453  */
  1689  */
  1454 function get_theme_support( $feature ) {
  1690 function get_theme_support( $feature ) {
  1455 	global $_wp_theme_features;
  1691 	global $_wp_theme_features;
  1456 	if ( ! isset( $_wp_theme_features[ $feature ] ) )
  1692 	if ( ! isset( $_wp_theme_features[ $feature ] ) )
  1457 		return false;
  1693 		return false;
  1464 		case 'custom-header' :
  1700 		case 'custom-header' :
  1465 		case 'custom-background' :
  1701 		case 'custom-background' :
  1466 			if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) )
  1702 			if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) )
  1467 				return $_wp_theme_features[ $feature ][0][ $args[0] ];
  1703 				return $_wp_theme_features[ $feature ][0][ $args[0] ];
  1468 			return false;
  1704 			return false;
  1469 			break;
  1705 
  1470 		default :
  1706 		default :
  1471 			return $_wp_theme_features[ $feature ];
  1707 			return $_wp_theme_features[ $feature ];
  1472 			break;
       
  1473 	}
  1708 	}
  1474 }
  1709 }
  1475 
  1710 
  1476 /**
  1711 /**
  1477  * Allows a theme to de-register its support of a certain feature
  1712  * Allows a theme to de-register its support of a certain feature
  1480  * be used for child themes to override support from the parent theme.
  1715  * be used for child themes to override support from the parent theme.
  1481  *
  1716  *
  1482  * @since 3.0.0
  1717  * @since 3.0.0
  1483  * @see add_theme_support()
  1718  * @see add_theme_support()
  1484  * @param string $feature the feature being added
  1719  * @param string $feature the feature being added
  1485  * @return bool Whether feature was removed.
  1720  * @return null|bool Whether feature was removed.
  1486  */
  1721  */
  1487 function remove_theme_support( $feature ) {
  1722 function remove_theme_support( $feature ) {
  1488 	// Blacklist: for internal registrations not used directly by themes.
  1723 	// Blacklist: for internal registrations not used directly by themes.
  1489 	if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) )
  1724 	if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) )
  1490 		return false;
  1725 		return false;
  1495 /**
  1730 /**
  1496  * Do not use. Removes theme support internally, ignorant of the blacklist.
  1731  * Do not use. Removes theme support internally, ignorant of the blacklist.
  1497  *
  1732  *
  1498  * @access private
  1733  * @access private
  1499  * @since 3.1.0
  1734  * @since 3.1.0
       
  1735  * @param string $feature
  1500  */
  1736  */
  1501 function _remove_theme_support( $feature ) {
  1737 function _remove_theme_support( $feature ) {
  1502 	global $_wp_theme_features;
  1738 	global $_wp_theme_features;
  1503 
  1739 
  1504 	switch ( $feature ) {
  1740 	switch ( $feature ) {
  1551 		return current_theme_supports( 'custom-header', 'uploads' );
  1787 		return current_theme_supports( 'custom-header', 'uploads' );
  1552 
  1788 
  1553 	if ( !isset( $_wp_theme_features[$feature] ) )
  1789 	if ( !isset( $_wp_theme_features[$feature] ) )
  1554 		return false;
  1790 		return false;
  1555 
  1791 
       
  1792 	if ( 'title-tag' == $feature ) {
       
  1793 		// Don't confirm support unless called internally.
       
  1794 		$trace = debug_backtrace();
       
  1795 		if ( ! in_array( $trace[1]['function'], array( '_wp_render_title_tag', 'wp_title' ) ) ) {
       
  1796 			return false;
       
  1797 		}
       
  1798 	}
       
  1799 
  1556 	// If no args passed then no extra checks need be performed
  1800 	// If no args passed then no extra checks need be performed
  1557 	if ( func_num_args() <= 1 )
  1801 	if ( func_num_args() <= 1 )
  1558 		return true;
  1802 		return true;
  1559 
  1803 
  1560 	$args = array_slice( func_get_args(), 1 );
  1804 	$args = array_slice( func_get_args(), 1 );
  1566 			// any type is accepted
  1810 			// any type is accepted
  1567 			if ( true === $_wp_theme_features[$feature] )  // Registered for all types
  1811 			if ( true === $_wp_theme_features[$feature] )  // Registered for all types
  1568 				return true;
  1812 				return true;
  1569 			$content_type = $args[0];
  1813 			$content_type = $args[0];
  1570 			return in_array( $content_type, $_wp_theme_features[$feature][0] );
  1814 			return in_array( $content_type, $_wp_theme_features[$feature][0] );
  1571 			break;
       
  1572 
  1815 
  1573 		case 'html5':
  1816 		case 'html5':
  1574 		case 'post-formats':
  1817 		case 'post-formats':
  1575 			// specific post formats can be registered by passing an array of types to
  1818 			// specific post formats can be registered by passing an array of types to
  1576 			// add_theme_support()
  1819 			// add_theme_support()
  1577 
  1820 
  1578 			// Specific areas of HTML5 support *must* be passed via an array to add_theme_support()
  1821 			// Specific areas of HTML5 support *must* be passed via an array to add_theme_support()
  1579 
  1822 
  1580 			$type = $args[0];
  1823 			$type = $args[0];
  1581 			return in_array( $type, $_wp_theme_features[$feature][0] );
  1824 			return in_array( $type, $_wp_theme_features[$feature][0] );
  1582 			break;
       
  1583 
  1825 
  1584 		case 'custom-header':
  1826 		case 'custom-header':
  1585 		case 'custom-background' :
  1827 		case 'custom-background' :
  1586 			// specific custom header and background capabilities can be registered by passing
  1828 			// specific custom header and background capabilities can be registered by passing
  1587 			// an array to add_theme_support()
  1829 			// an array to add_theme_support()
  1588 			$header_support = $args[0];
  1830 			$header_support = $args[0];
  1589 			return ( isset( $_wp_theme_features[$feature][0][$header_support] ) && $_wp_theme_features[$feature][0][$header_support] );
  1831 			return ( isset( $_wp_theme_features[$feature][0][$header_support] ) && $_wp_theme_features[$feature][0][$header_support] );
  1590 			break;
  1832 	}
  1591 	}
  1833 
  1592 
  1834 	/**
  1593 	return apply_filters('current_theme_supports-' . $feature, true, $args, $_wp_theme_features[$feature]);
  1835 	 * Filter whether the current theme supports a specific feature.
       
  1836 	 *
       
  1837 	 * The dynamic portion of the hook name, `$feature`, refers to the specific theme
       
  1838 	 * feature. Possible values include 'post-formats', 'post-thumbnails', 'custom-background',
       
  1839 	 * 'custom-header', 'menus', 'automatic-feed-links', and 'html5'.
       
  1840 	 *
       
  1841 	 * @since 3.4.0
       
  1842 	 *
       
  1843 	 * @param bool   true     Whether the current theme supports the given feature. Default true.
       
  1844 	 * @param array  $args    Array of arguments for the feature.
       
  1845 	 * @param string $feature The theme feature.
       
  1846 	 */
       
  1847 	return apply_filters( "current_theme_supports-{$feature}", true, $args, $_wp_theme_features[$feature] );
  1594 }
  1848 }
  1595 
  1849 
  1596 /**
  1850 /**
  1597  * Checks a theme's support for a given feature before loading the functions which implement it.
  1851  * Checks a theme's support for a given feature before loading the functions which implement it.
  1598  *
  1852  *
  1599  * @since 2.9.0
  1853  * @since 2.9.0
  1600  * @param string $feature the feature being checked
  1854  *
  1601  * @param string $include the file containing the functions that implement the feature
  1855  * @param string $feature The feature being checked.
  1602  */
  1856  * @param string $include Path to the file.
  1603 function require_if_theme_supports( $feature, $include) {
  1857  * @return bool True if the current theme supports the supplied feature, false otherwise.
  1604 	if ( current_theme_supports( $feature ) )
  1858  */
       
  1859 function require_if_theme_supports( $feature, $include ) {
       
  1860 	if ( current_theme_supports( $feature ) ) {
  1605 		require ( $include );
  1861 		require ( $include );
       
  1862 		return true;
       
  1863 	}
       
  1864 	return false;
  1606 }
  1865 }
  1607 
  1866 
  1608 /**
  1867 /**
  1609  * Checks an attachment being deleted to see if it's a header or background image.
  1868  * Checks an attachment being deleted to see if it's a header or background image.
  1610  *
  1869  *
  1625 
  1884 
  1626 	if ( $background_image && $background_image == $attachment_image )
  1885 	if ( $background_image && $background_image == $attachment_image )
  1627 		remove_theme_mod( 'background_image' );
  1886 		remove_theme_mod( 'background_image' );
  1628 }
  1887 }
  1629 
  1888 
  1630 add_action( 'delete_attachment', '_delete_attachment_theme_mod' );
       
  1631 
       
  1632 /**
  1889 /**
  1633  * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load
  1890  * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load
  1634  *
  1891  *
  1635  * @since 3.3.0
  1892  * @since 3.3.0
  1636  */
  1893  */
  1637 function check_theme_switched() {
  1894 function check_theme_switched() {
  1638 	if ( $stylesheet = get_option( 'theme_switched' ) ) {
  1895 	if ( $stylesheet = get_option( 'theme_switched' ) ) {
  1639 		$old_theme = wp_get_theme( $stylesheet );
  1896 		$old_theme = wp_get_theme( $stylesheet );
  1640 
  1897 
  1641 		if ( $old_theme->exists() )
  1898 		// Prevent retrieve_widgets() from running since Customizer already called it up front
  1642 			do_action( 'after_switch_theme', $old_theme->get('Name'), $old_theme );
  1899 		if ( get_option( 'theme_switched_via_customizer' ) ) {
  1643 		else
  1900 			remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
       
  1901 			update_option( 'theme_switched_via_customizer', false );
       
  1902 		}
       
  1903 
       
  1904 		if ( $old_theme->exists() ) {
       
  1905 			/**
       
  1906 			 * Fires on the first WP load after a theme switch if the old theme still exists.
       
  1907 			 *
       
  1908 			 * This action fires multiple times and the parameters differs
       
  1909 			 * according to the context, if the old theme exists or not.
       
  1910 			 * If the old theme is missing, the parameter will be the slug
       
  1911 			 * of the old theme.
       
  1912 			 *
       
  1913 			 * @since 3.3.0
       
  1914 			 *
       
  1915 			 * @param string   $old_name  Old theme name.
       
  1916 			 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
       
  1917 			 */
       
  1918 			do_action( 'after_switch_theme', $old_theme->get( 'Name' ), $old_theme );
       
  1919 		} else {
       
  1920 			/** This action is documented in wp-includes/theme.php */
  1644 			do_action( 'after_switch_theme', $stylesheet );
  1921 			do_action( 'after_switch_theme', $stylesheet );
       
  1922 		}
  1645 
  1923 
  1646 		update_option( 'theme_switched', false );
  1924 		update_option( 'theme_switched', false );
  1647 	}
  1925 	}
  1648 }
  1926 }
  1649 
  1927 
  1662 
  1940 
  1663 	require( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
  1941 	require( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
  1664 	// Init Customize class
  1942 	// Init Customize class
  1665 	$GLOBALS['wp_customize'] = new WP_Customize_Manager;
  1943 	$GLOBALS['wp_customize'] = new WP_Customize_Manager;
  1666 }
  1944 }
  1667 add_action( 'plugins_loaded', '_wp_customize_include' );
       
  1668 
  1945 
  1669 /**
  1946 /**
  1670  * Adds settings for the customize-loader script.
  1947  * Adds settings for the customize-loader script.
  1671  *
  1948  *
  1672  * @since 3.4.0
  1949  * @since 3.4.0
  1685 
  1962 
  1686 	$settings = array(
  1963 	$settings = array(
  1687 		'url'           => esc_url( admin_url( 'customize.php' ) ),
  1964 		'url'           => esc_url( admin_url( 'customize.php' ) ),
  1688 		'isCrossDomain' => $cross_domain,
  1965 		'isCrossDomain' => $cross_domain,
  1689 		'browser'       => $browser,
  1966 		'browser'       => $browser,
       
  1967 		'l10n'          => array(
       
  1968 			'saveAlert'       => __( 'The changes you made will be lost if you navigate away from this page.' ),
       
  1969 			'mainIframeTitle' => __( 'Customizer' ),
       
  1970 		),
  1690 	);
  1971 	);
  1691 
  1972 
  1692 	$script = 'var _wpCustomizeLoaderSettings = ' . json_encode( $settings ) . ';';
  1973 	$script = 'var _wpCustomizeLoaderSettings = ' . wp_json_encode( $settings ) . ';';
  1693 
  1974 
  1694 	$data = $wp_scripts->get_data( 'customize-loader', 'data' );
  1975 	$data = $wp_scripts->get_data( 'customize-loader', 'data' );
  1695 	if ( $data )
  1976 	if ( $data )
  1696 		$script = "$data\n$script";
  1977 		$script = "$data\n$script";
  1697 
  1978 
  1698 	$wp_scripts->add_data( 'customize-loader', 'data', $script );
  1979 	$wp_scripts->add_data( 'customize-loader', 'data', $script );
  1699 }
  1980 }
  1700 add_action( 'admin_enqueue_scripts', '_wp_customize_loader_settings' );
  1981 
  1701 
  1982 /**
  1702 /**
  1983  * Returns a URL to load the Customizer.
  1703  * Returns a URL to load the theme customizer.
       
  1704  *
  1984  *
  1705  * @since 3.4.0
  1985  * @since 3.4.0
  1706  *
  1986  *
  1707  * @param string $stylesheet Optional. Theme to customize. Defaults to current theme.
  1987  * @param string $stylesheet Optional. Theme to customize. Defaults to current theme.
  1708  * 	The theme's stylesheet will be urlencoded if necessary.
  1988  * 	The theme's stylesheet will be urlencoded if necessary.
  1713 		$url .= '?theme=' . urlencode( $stylesheet );
  1993 		$url .= '?theme=' . urlencode( $stylesheet );
  1714 	return esc_url( $url );
  1994 	return esc_url( $url );
  1715 }
  1995 }
  1716 
  1996 
  1717 /**
  1997 /**
  1718  * Prints a script to check whether or not the customizer is supported,
  1998  * Prints a script to check whether or not the Customizer is supported,
  1719  * and apply either the no-customize-support or customize-support class
  1999  * and apply either the no-customize-support or customize-support class
  1720  * to the body.
  2000  * to the body.
  1721  *
  2001  *
  1722  * This function MUST be called inside the body tag.
  2002  * This function MUST be called inside the body tag.
  1723  *
  2003  *
  1749 			b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
  2029 			b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
  1750 		}());
  2030 		}());
  1751 	</script>
  2031 	</script>
  1752 	<?php
  2032 	<?php
  1753 }
  2033 }
       
  2034 
       
  2035 /**
       
  2036  * Whether the site is being previewed in the Customizer.
       
  2037  *
       
  2038  * @since 4.0.0
       
  2039  *
       
  2040  * @global WP_Customize_Manager $wp_customize Customizer instance.
       
  2041  *
       
  2042  * @return bool True if the site is being previewed in the Customizer, false otherwise.
       
  2043  */
       
  2044 function is_customize_preview() {
       
  2045 	global $wp_customize;
       
  2046 
       
  2047 	return ( $wp_customize instanceof WP_Customize_Manager ) && $wp_customize->is_preview();
       
  2048 }