wp/wp-includes/theme.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    11  *
    11  *
    12  * Despite advances over get_themes(), this function is quite expensive, and grows
    12  * Despite advances over get_themes(), this function is quite expensive, and grows
    13  * linearly with additional themes. Stick to wp_get_theme() if possible.
    13  * linearly with additional themes. Stick to wp_get_theme() if possible.
    14  *
    14  *
    15  * @since 3.4.0
    15  * @since 3.4.0
       
    16  *
       
    17  * @global array $wp_theme_directories
       
    18  * @staticvar array $_themes
    16  *
    19  *
    17  * @param array $args The search arguments. Optional.
    20  * @param array $args The search arguments. Optional.
    18  * - errors      mixed  True to return themes with errors, false to return themes without errors, null
    21  * - errors      mixed  True to return themes with errors, false to return themes without errors, null
    19  *                      to return all themes. Defaults to false.
    22  *                      to return all themes. Defaults to false.
    20  * - allowed     mixed  (Multisite) True to return only allowed themes for a site. False to return only
    23  * - allowed     mixed  (Multisite) True to return only allowed themes for a site. False to return only
    21  *                      disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
    24  *                      disallowed themes for a site. 'site' to return only site-allowed themes. 'network'
    22  *                      to return only network-allowed themes. Null to return all themes. Defaults to null.
    25  *                      to return only network-allowed themes. Null to return all themes. Defaults to null.
    23  * - blog_id     int    (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
    26  * - blog_id     int    (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0,
    24  *                      synonymous for the current blog.
    27  *                      synonymous for the current blog.
    25  * @return Array of WP_Theme objects.
    28  * @return array Array of WP_Theme objects.
    26  */
    29  */
    27 function wp_get_themes( $args = array() ) {
    30 function wp_get_themes( $args = array() ) {
    28 	global $wp_theme_directories;
    31 	global $wp_theme_directories;
    29 
    32 
    30 	$defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
    33 	$defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 );
    31 	$args = wp_parse_args( $args, $defaults );
    34 	$args = wp_parse_args( $args, $defaults );
    32 
    35 
    33 	$theme_directories = search_theme_directories();
    36 	$theme_directories = search_theme_directories();
    34 
    37 
    35 	if ( count( $wp_theme_directories ) > 1 ) {
    38 	if ( is_array( $wp_theme_directories ) && count( $wp_theme_directories ) > 1 ) {
    36 		// Make sure the current theme wins out, in case search_theme_directories() picks the wrong
    39 		// Make sure the current theme wins out, in case search_theme_directories() picks the wrong
    37 		// one in the case of a conflict. (Normally, last registered theme root wins.)
    40 		// one in the case of a conflict. (Normally, last registered theme root wins.)
    38 		$current_theme = get_stylesheet();
    41 		$current_theme = get_stylesheet();
    39 		if ( isset( $theme_directories[ $current_theme ] ) ) {
    42 		if ( isset( $theme_directories[ $current_theme ] ) ) {
    40 			$root_of_current_theme = get_raw_theme_root( $current_theme );
    43 			$root_of_current_theme = get_raw_theme_root( $current_theme );
    82 /**
    85 /**
    83  * Gets a WP_Theme object for a theme.
    86  * Gets a WP_Theme object for a theme.
    84  *
    87  *
    85  * @since 3.4.0
    88  * @since 3.4.0
    86  *
    89  *
       
    90  * @global array $wp_theme_directories
       
    91  *
    87  * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
    92  * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
    88  * @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root()
    93  * @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root()
    89  * 	is used to calculate the theme root for the $stylesheet provided (or current theme).
    94  * 	                         is used to calculate the theme root for the $stylesheet provided (or current theme).
    90  * @return WP_Theme Theme object. Be sure to check the object's exists() method if you need to confirm the theme's existence.
    95  * @return WP_Theme Theme object. Be sure to check the object's exists() method if you need to confirm the theme's existence.
    91  */
    96  */
    92 function wp_get_theme( $stylesheet = null, $theme_root = null ) {
    97 function wp_get_theme( $stylesheet = null, $theme_root = null ) {
    93 	global $wp_theme_directories;
    98 	global $wp_theme_directories;
    94 
    99 
   144  *
   149  *
   145  * @return string Stylesheet name.
   150  * @return string Stylesheet name.
   146  */
   151  */
   147 function get_stylesheet() {
   152 function get_stylesheet() {
   148 	/**
   153 	/**
   149 	 * Filter the name of current stylesheet.
   154 	 * Filters the name of current stylesheet.
   150 	 *
   155 	 *
   151 	 * @since 1.5.0
   156 	 * @since 1.5.0
   152 	 *
   157 	 *
   153 	 * @param string $stylesheet Name of the current stylesheet.
   158 	 * @param string $stylesheet Name of the current stylesheet.
   154 	 */
   159 	 */
   166 	$stylesheet = get_stylesheet();
   171 	$stylesheet = get_stylesheet();
   167 	$theme_root = get_theme_root( $stylesheet );
   172 	$theme_root = get_theme_root( $stylesheet );
   168 	$stylesheet_dir = "$theme_root/$stylesheet";
   173 	$stylesheet_dir = "$theme_root/$stylesheet";
   169 
   174 
   170 	/**
   175 	/**
   171 	 * Filter the stylesheet directory path for current theme.
   176 	 * Filters the stylesheet directory path for current theme.
   172 	 *
   177 	 *
   173 	 * @since 1.5.0
   178 	 * @since 1.5.0
   174 	 *
   179 	 *
   175 	 * @param string $stylesheet_dir Absolute path to the current them.
   180 	 * @param string $stylesheet_dir Absolute path to the current theme.
   176 	 * @param string $stylesheet     Directory name of the current theme.
   181 	 * @param string $stylesheet     Directory name of the current theme.
   177 	 * @param string $theme_root     Absolute path to themes directory.
   182 	 * @param string $theme_root     Absolute path to themes directory.
   178 	 */
   183 	 */
   179 	return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root );
   184 	return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root );
   180 }
   185 }
   190 	$stylesheet = str_replace( '%2F', '/', rawurlencode( get_stylesheet() ) );
   195 	$stylesheet = str_replace( '%2F', '/', rawurlencode( get_stylesheet() ) );
   191 	$theme_root_uri = get_theme_root_uri( $stylesheet );
   196 	$theme_root_uri = get_theme_root_uri( $stylesheet );
   192 	$stylesheet_dir_uri = "$theme_root_uri/$stylesheet";
   197 	$stylesheet_dir_uri = "$theme_root_uri/$stylesheet";
   193 
   198 
   194 	/**
   199 	/**
   195 	 * Filter the stylesheet directory URI.
   200 	 * Filters the stylesheet directory URI.
   196 	 *
   201 	 *
   197 	 * @since 1.5.0
   202 	 * @since 1.5.0
   198 	 *
   203 	 *
   199 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
   204 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
   200 	 * @param string $stylesheet         Name of the activated theme's directory.
   205 	 * @param string $stylesheet         Name of the activated theme's directory.
   202 	 */
   207 	 */
   203 	return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri );
   208 	return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri );
   204 }
   209 }
   205 
   210 
   206 /**
   211 /**
   207  * Retrieve URI of current theme stylesheet.
   212  * Retrieves the URI of current theme stylesheet.
   208  *
   213  *
   209  * The stylesheet file name is 'style.css' which is appended to {@link
   214  * The stylesheet file name is 'style.css' which is appended to the stylesheet directory URI path.
   210  * get_stylesheet_directory_uri() stylesheet directory URI} path.
   215  * See get_stylesheet_directory_uri().
   211  *
   216  *
   212  * @since 1.5.0
   217  * @since 1.5.0
   213  *
   218  *
   214  * @return string
   219  * @return string
   215  */
   220  */
   216 function get_stylesheet_uri() {
   221 function get_stylesheet_uri() {
   217 	$stylesheet_dir_uri = get_stylesheet_directory_uri();
   222 	$stylesheet_dir_uri = get_stylesheet_directory_uri();
   218 	$stylesheet_uri = $stylesheet_dir_uri . '/style.css';
   223 	$stylesheet_uri = $stylesheet_dir_uri . '/style.css';
   219 	/**
   224 	/**
   220 	 * Filter the URI of the current theme stylesheet.
   225 	 * Filters the URI of the current theme stylesheet.
   221 	 *
   226 	 *
   222 	 * @since 1.5.0
   227 	 * @since 1.5.0
   223 	 *
   228 	 *
   224 	 * @param string $stylesheet_uri     Stylesheet URI for the current theme/child theme.
   229 	 * @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.
   230 	 * @param string $stylesheet_dir_uri Stylesheet directory URI for the current theme/child theme.
   226 	 */
   231 	 */
   227 	return apply_filters( 'stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri );
   232 	return apply_filters( 'stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri );
   228 }
   233 }
   229 
   234 
   230 /**
   235 /**
   231  * Retrieve localized stylesheet URI.
   236  * Retrieves the localized stylesheet URI.
   232  *
   237  *
   233  * The stylesheet directory for the localized stylesheet files are located, by
   238  * The stylesheet directory for the localized stylesheet files are located, by
   234  * default, in the base theme directory. The name of the locale file will be the
   239  * default, in the base theme directory. The name of the locale file will be the
   235  * locale followed by '.css'. If that does not exist, then the text direction
   240  * locale followed by '.css'. If that does not exist, then the text direction
   236  * stylesheet will be checked for existence, for example 'ltr.css'.
   241  * stylesheet will be checked for existence, for example 'ltr.css'.
   237  *
   242  *
   238  * The theme may change the location of the stylesheet directory by either using
   243  * The theme may change the location of the stylesheet directory by either using
   239  * the 'stylesheet_directory_uri' filter or the 'locale_stylesheet_uri' filter.
   244  * the {@see 'stylesheet_directory_uri'} or {@see 'locale_stylesheet_uri'} filters.
       
   245  *
   240  * If you want to change the location of the stylesheet files for the entire
   246  * If you want to change the location of the stylesheet files for the entire
   241  * WordPress workflow, then change the former. If you just have the locale in a
   247  * WordPress workflow, then change the former. If you just have the locale in a
   242  * separate folder, then change the latter.
   248  * separate folder, then change the latter.
   243  *
   249  *
   244  * @since 2.1.0
   250  * @since 2.1.0
       
   251  *
       
   252  * @global WP_Locale $wp_locale
   245  *
   253  *
   246  * @return string
   254  * @return string
   247  */
   255  */
   248 function get_locale_stylesheet_uri() {
   256 function get_locale_stylesheet_uri() {
   249 	global $wp_locale;
   257 	global $wp_locale;
   255 	elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") )
   263 	elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") )
   256 		$stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css";
   264 		$stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css";
   257 	else
   265 	else
   258 		$stylesheet_uri = '';
   266 		$stylesheet_uri = '';
   259 	/**
   267 	/**
   260 	 * Filter the localized stylesheet URI.
   268 	 * Filters the localized stylesheet URI.
   261 	 *
   269 	 *
   262 	 * @since 2.1.0
   270 	 * @since 2.1.0
   263 	 *
   271 	 *
   264 	 * @param string $stylesheet_uri     Localized stylesheet URI.
   272 	 * @param string $stylesheet_uri     Localized stylesheet URI.
   265 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
   273 	 * @param string $stylesheet_dir_uri Stylesheet directory URI.
   274  *
   282  *
   275  * @return string Template name.
   283  * @return string Template name.
   276  */
   284  */
   277 function get_template() {
   285 function get_template() {
   278 	/**
   286 	/**
   279 	 * Filter the name of the current theme.
   287 	 * Filters the name of the current theme.
   280 	 *
   288 	 *
   281 	 * @since 1.5.0
   289 	 * @since 1.5.0
   282 	 *
   290 	 *
   283 	 * @param string $template Current theme's directory name.
   291 	 * @param string $template Current theme's directory name.
   284 	 */
   292 	 */
   296 	$template = get_template();
   304 	$template = get_template();
   297 	$theme_root = get_theme_root( $template );
   305 	$theme_root = get_theme_root( $template );
   298 	$template_dir = "$theme_root/$template";
   306 	$template_dir = "$theme_root/$template";
   299 
   307 
   300 	/**
   308 	/**
   301 	 * Filter the current theme directory path.
   309 	 * Filters the current theme directory path.
   302 	 *
   310 	 *
   303 	 * @since 1.5.0
   311 	 * @since 1.5.0
   304 	 *
   312 	 *
   305 	 * @param string $template_dir The URI of the current theme directory.
   313 	 * @param string $template_dir The URI of the current theme directory.
   306 	 * @param string $template     Directory name of the current theme.
   314 	 * @param string $template     Directory name of the current theme.
   320 	$template = str_replace( '%2F', '/', rawurlencode( get_template() ) );
   328 	$template = str_replace( '%2F', '/', rawurlencode( get_template() ) );
   321 	$theme_root_uri = get_theme_root_uri( $template );
   329 	$theme_root_uri = get_theme_root_uri( $template );
   322 	$template_dir_uri = "$theme_root_uri/$template";
   330 	$template_dir_uri = "$theme_root_uri/$template";
   323 
   331 
   324 	/**
   332 	/**
   325 	 * Filter the current theme directory URI.
   333 	 * Filters the current theme directory URI.
   326 	 *
   334 	 *
   327 	 * @since 1.5.0
   335 	 * @since 1.5.0
   328 	 *
   336 	 *
   329 	 * @param string $template_dir_uri The URI of the current theme directory.
   337 	 * @param string $template_dir_uri The URI of the current theme directory.
   330 	 * @param string $template         Directory name of the current theme.
   338 	 * @param string $template         Directory name of the current theme.
   336 /**
   344 /**
   337  * Retrieve theme roots.
   345  * Retrieve theme roots.
   338  *
   346  *
   339  * @since 2.9.0
   347  * @since 2.9.0
   340  *
   348  *
       
   349  * @global array $wp_theme_directories
       
   350  *
   341  * @return array|string An array of theme roots keyed by template/stylesheet or a single theme root if all themes have the same root.
   351  * @return array|string An array of theme roots keyed by template/stylesheet or a single theme root if all themes have the same root.
   342  */
   352  */
   343 function get_theme_roots() {
   353 function get_theme_roots() {
   344 	global $wp_theme_directories;
   354 	global $wp_theme_directories;
   345 
   355 
   346 	if ( count($wp_theme_directories) <= 1 )
   356 	if ( ! is_array( $wp_theme_directories ) || count( $wp_theme_directories ) <= 1 ) {
   347 		return '/themes';
   357 		return '/themes';
       
   358 	}
   348 
   359 
   349 	$theme_roots = get_site_transient( 'theme_roots' );
   360 	$theme_roots = get_site_transient( 'theme_roots' );
   350 	if ( false === $theme_roots ) {
   361 	if ( false === $theme_roots ) {
   351 		search_theme_directories( true ); // Regenerate the transient.
   362 		search_theme_directories( true ); // Regenerate the transient.
   352 		$theme_roots = get_site_transient( 'theme_roots' );
   363 		$theme_roots = get_site_transient( 'theme_roots' );
   356 
   367 
   357 /**
   368 /**
   358  * Register a directory that contains themes.
   369  * Register a directory that contains themes.
   359  *
   370  *
   360  * @since 2.9.0
   371  * @since 2.9.0
       
   372  *
       
   373  * @global array $wp_theme_directories
   361  *
   374  *
   362  * @param string $directory Either the full filesystem path to a theme folder or a folder within WP_CONTENT_DIR
   375  * @param string $directory Either the full filesystem path to a theme folder or a folder within WP_CONTENT_DIR
   363  * @return bool
   376  * @return bool
   364  */
   377  */
   365 function register_theme_directory( $directory ) {
   378 function register_theme_directory( $directory ) {
   389 /**
   402 /**
   390  * Search all registered theme directories for complete and valid themes.
   403  * Search all registered theme directories for complete and valid themes.
   391  *
   404  *
   392  * @since 2.9.0
   405  * @since 2.9.0
   393  *
   406  *
       
   407  * @global array $wp_theme_directories
       
   408  * @staticvar array $found_themes
       
   409  *
   394  * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
   410  * @param bool $force Optional. Whether to force a new directory scan. Defaults to false.
   395  * @return array Valid themes found
   411  * @return array|false Valid themes found
   396  */
   412  */
   397 function search_theme_directories( $force = false ) {
   413 function search_theme_directories( $force = false ) {
   398 	global $wp_theme_directories;
   414 	global $wp_theme_directories;
       
   415 	static $found_themes = null;
       
   416 
   399 	if ( empty( $wp_theme_directories ) )
   417 	if ( empty( $wp_theme_directories ) )
   400 		return false;
   418 		return false;
   401 
   419 
   402 	static $found_themes;
       
   403 	if ( ! $force && isset( $found_themes ) )
   420 	if ( ! $force && isset( $found_themes ) )
   404 		return $found_themes;
   421 		return $found_themes;
   405 
   422 
   406 	$found_themes = array();
   423 	$found_themes = array();
   407 
   424 
   417 		else
   434 		else
   418 			$relative_theme_roots[ $theme_root ] = $theme_root;
   435 			$relative_theme_roots[ $theme_root ] = $theme_root;
   419 	}
   436 	}
   420 
   437 
   421 	/**
   438 	/**
   422 	 * Filter whether to get the cache of the registered theme directories.
   439 	 * Filters whether to get the cache of the registered theme directories.
   423 	 *
   440 	 *
   424 	 * @since 3.4.0
   441 	 * @since 3.4.0
   425 	 *
   442 	 *
   426 	 * @param bool   $cache_expiration Whether to get the cache of the theme directories. Default false.
   443 	 * @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.
   444 	 * @param string $cache_directory  Directory to be searched for the cache.
   516  *
   533  *
   517  * Does not have trailing slash.
   534  * Does not have trailing slash.
   518  *
   535  *
   519  * @since 1.5.0
   536  * @since 1.5.0
   520  *
   537  *
       
   538  * @global array $wp_theme_directories
       
   539  *
   521  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   540  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   522  * @return string Theme path.
   541  * @return string Theme path.
   523  */
   542  */
   524 function get_theme_root( $stylesheet_or_template = false ) {
   543 function get_theme_root( $stylesheet_or_template = false ) {
   525 	global $wp_theme_directories;
   544 	global $wp_theme_directories;
   532 	} else {
   551 	} else {
   533 		$theme_root = WP_CONTENT_DIR . '/themes';
   552 		$theme_root = WP_CONTENT_DIR . '/themes';
   534 	}
   553 	}
   535 
   554 
   536 	/**
   555 	/**
   537 	 * Filter the absolute path to the themes directory.
   556 	 * Filters the absolute path to the themes directory.
   538 	 *
   557 	 *
   539 	 * @since 1.5.0
   558 	 * @since 1.5.0
   540 	 *
   559 	 *
   541 	 * @param string $theme_root Absolute path to themes directory.
   560 	 * @param string $theme_root Absolute path to themes directory.
   542 	 */
   561 	 */
   548  *
   567  *
   549  * Does not have trailing slash.
   568  * Does not have trailing slash.
   550  *
   569  *
   551  * @since 1.5.0
   570  * @since 1.5.0
   552  *
   571  *
       
   572  * @global array $wp_theme_directories
       
   573  *
   553  * @param string $stylesheet_or_template Optional. The stylesheet or template name of the theme.
   574  * @param string $stylesheet_or_template Optional. The stylesheet or template name of the theme.
   554  * 	Default is to leverage the main theme root.
   575  * 	                                     Default is to leverage the main theme root.
   555  * @param string $theme_root Optional. The theme root for which calculations will be based, preventing
   576  * @param string $theme_root             Optional. The theme root for which calculations will be based, preventing
   556  * 	the need for a get_raw_theme_root() call.
   577  * 	                                     the need for a get_raw_theme_root() call.
   557  * @return string Themes URI.
   578  * @return string Themes URI.
   558  */
   579  */
   559 function get_theme_root_uri( $stylesheet_or_template = false, $theme_root = false ) {
   580 function get_theme_root_uri( $stylesheet_or_template = false, $theme_root = false ) {
   560 	global $wp_theme_directories;
   581 	global $wp_theme_directories;
   561 
   582 
   579 	} else {
   600 	} else {
   580 		$theme_root_uri = content_url( 'themes' );
   601 		$theme_root_uri = content_url( 'themes' );
   581 	}
   602 	}
   582 
   603 
   583 	/**
   604 	/**
   584 	 * Filter the URI for themes directory.
   605 	 * Filters the URI for themes directory.
   585 	 *
   606 	 *
   586 	 * @since 1.5.0
   607 	 * @since 1.5.0
   587 	 *
   608 	 *
   588 	 * @param string $theme_root_uri         The URI for themes directory.
   609 	 * @param string $theme_root_uri         The URI for themes directory.
   589 	 * @param string $siteurl                WordPress web address which is set in General Options.
   610 	 * @param string $siteurl                WordPress web address which is set in General Options.
   595 /**
   616 /**
   596  * Get the raw theme root relative to the content directory with no filters applied.
   617  * Get the raw theme root relative to the content directory with no filters applied.
   597  *
   618  *
   598  * @since 3.1.0
   619  * @since 3.1.0
   599  *
   620  *
       
   621  * @global array $wp_theme_directories
       
   622  *
   600  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   623  * @param string $stylesheet_or_template The stylesheet or template name of the theme
   601  * @param bool $skip_cache Optional. Whether to skip the cache. Defaults to false, meaning the cache is used.
   624  * @param bool   $skip_cache             Optional. Whether to skip the cache.
       
   625  *                                       Defaults to false, meaning the cache is used.
   602  * @return string Theme root
   626  * @return string Theme root
   603  */
   627  */
   604 function get_raw_theme_root( $stylesheet_or_template, $skip_cache = false ) {
   628 function get_raw_theme_root( $stylesheet_or_template, $skip_cache = false ) {
   605 	global $wp_theme_directories;
   629 	global $wp_theme_directories;
   606 
   630 
   607 	if ( count($wp_theme_directories) <= 1 )
   631 	if ( ! is_array( $wp_theme_directories ) || count( $wp_theme_directories ) <= 1 ) {
   608 		return '/themes';
   632 		return '/themes';
       
   633 	}
   609 
   634 
   610 	$theme_root = false;
   635 	$theme_root = false;
   611 
   636 
   612 	// If requesting the root for the current theme, consult options to avoid calling get_theme_roots()
   637 	// If requesting the root for the current theme, consult options to avoid calling get_theme_roots()
   613 	if ( ! $skip_cache ) {
   638 	if ( ! $skip_cache ) {
   637 		return;
   662 		return;
   638 	echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />';
   663 	echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />';
   639 }
   664 }
   640 
   665 
   641 /**
   666 /**
   642  * Start preview theme output buffer.
       
   643  *
       
   644  * Will only perform task if the user has permissions and template and preview
       
   645  * query variables exist.
       
   646  *
       
   647  * @since 2.6.0
       
   648  */
       
   649 function preview_theme() {
       
   650 	if ( ! (isset($_GET['template']) && isset($_GET['preview'])) )
       
   651 		return;
       
   652 
       
   653 	if ( !current_user_can( 'switch_themes' ) )
       
   654 		return;
       
   655 
       
   656 	// Admin Thickbox requests
       
   657 	if ( isset( $_GET['preview_iframe'] ) )
       
   658 		show_admin_bar( false );
       
   659 
       
   660 	$_GET['template'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['template']);
       
   661 
       
   662 	if ( validate_file($_GET['template']) )
       
   663 		return;
       
   664 
       
   665 	add_filter( 'template', '_preview_theme_template_filter' );
       
   666 
       
   667 	if ( isset($_GET['stylesheet']) ) {
       
   668 		$_GET['stylesheet'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['stylesheet']);
       
   669 		if ( validate_file($_GET['stylesheet']) )
       
   670 			return;
       
   671 		add_filter( 'stylesheet', '_preview_theme_stylesheet_filter' );
       
   672 	}
       
   673 
       
   674 	// Prevent theme mods to current theme being used on theme being previewed
       
   675 	add_filter( 'pre_option_theme_mods_' . get_option( 'stylesheet' ), '__return_empty_array' );
       
   676 
       
   677 	ob_start( 'preview_theme_ob_filter' );
       
   678 }
       
   679 
       
   680 /**
       
   681  * Private function to modify the current template when previewing a theme
       
   682  *
       
   683  * @since 2.9.0
       
   684  * @access private
       
   685  *
       
   686  * @return string
       
   687  */
       
   688 function _preview_theme_template_filter() {
       
   689 	return isset($_GET['template']) ? $_GET['template'] : '';
       
   690 }
       
   691 
       
   692 /**
       
   693  * Private function to modify the current stylesheet when previewing a theme
       
   694  *
       
   695  * @since 2.9.0
       
   696  * @access private
       
   697  *
       
   698  * @return string
       
   699  */
       
   700 function _preview_theme_stylesheet_filter() {
       
   701 	return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : '';
       
   702 }
       
   703 
       
   704 /**
       
   705  * Callback function for ob_start() to capture all links in the theme.
       
   706  *
       
   707  * @since 2.6.0
       
   708  * @access private
       
   709  *
       
   710  * @param string $content
       
   711  * @return string
       
   712  */
       
   713 function preview_theme_ob_filter( $content ) {
       
   714 	return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content );
       
   715 }
       
   716 
       
   717 /**
       
   718  * Manipulates preview theme links in order to control and maintain location.
       
   719  *
       
   720  * Callback function for preg_replace_callback() to accept and filter matches.
       
   721  *
       
   722  * @since 2.6.0
       
   723  * @access private
       
   724  *
       
   725  * @param array $matches
       
   726  * @return string
       
   727  */
       
   728 function preview_theme_ob_filter_callback( $matches ) {
       
   729 	if ( strpos($matches[4], 'onclick') !== false )
       
   730 		$matches[4] = preg_replace('#onclick=([\'"]).*?(?<!\\\)\\1#i', '', $matches[4]); //Strip out any onclicks from rest of <a>. (?<!\\\) means to ignore the '" if it's escaped by \  to prevent breaking mid-attribute.
       
   731 	if (
       
   732 		( false !== strpos($matches[3], '/wp-admin/') )
       
   733 	||
       
   734 		( false !== strpos( $matches[3], '://' ) && 0 !== strpos( $matches[3], home_url() ) )
       
   735 	||
       
   736 		( false !== strpos($matches[3], '/feed/') )
       
   737 	||
       
   738 		( false !== strpos($matches[3], '/trackback/') )
       
   739 	)
       
   740 		return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4];
       
   741 
       
   742 	$stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : '';
       
   743 	$template   = isset( $_GET['template'] )   ? $_GET['template']   : '';
       
   744 
       
   745 	$link = add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => 1 ), $matches[3] );
       
   746 	if ( 0 === strpos($link, 'preview=1') )
       
   747 		$link = "?$link";
       
   748 	return $matches[1] . esc_attr( $link ) . $matches[4];
       
   749 }
       
   750 
       
   751 /**
       
   752  * Switches the theme.
   667  * Switches the theme.
   753  *
   668  *
   754  * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature
   669  * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature
   755  * of two arguments: $template then $stylesheet. This is for backwards compatibility.
   670  * of two arguments: $template then $stylesheet. This is for backward compatibility.
   756  *
   671  *
   757  * @since 2.5.0
   672  * @since 2.5.0
       
   673  *
       
   674  * @global array                $wp_theme_directories
       
   675  * @global WP_Customize_Manager $wp_customize
       
   676  * @global array                $sidebars_widgets
   758  *
   677  *
   759  * @param string $stylesheet Stylesheet name
   678  * @param string $stylesheet Stylesheet name
   760  */
   679  */
   761 function switch_theme( $stylesheet ) {
   680 function switch_theme( $stylesheet ) {
   762 	global $wp_theme_directories, $wp_customize, $sidebars_widgets;
   681 	global $wp_theme_directories, $wp_customize, $sidebars_widgets;
   763 
   682 
   764 	$_sidebars_widgets = null;
   683 	$_sidebars_widgets = null;
   765 	if ( 'wp_ajax_customize_save' === current_action() ) {
   684 	if ( 'wp_ajax_customize_save' === current_action() ) {
   766 		$_sidebars_widgets = $wp_customize->post_value( $wp_customize->get_setting( 'old_sidebars_widgets_data' ) );
   685 		$old_sidebars_widgets_data_setting = $wp_customize->get_setting( 'old_sidebars_widgets_data' );
       
   686 		if ( $old_sidebars_widgets_data_setting ) {
       
   687 			$_sidebars_widgets = $wp_customize->post_value( $old_sidebars_widgets_data_setting );
       
   688 		}
   767 	} elseif ( is_array( $sidebars_widgets ) ) {
   689 	} elseif ( is_array( $sidebars_widgets ) ) {
   768 		$_sidebars_widgets = $sidebars_widgets;
   690 		$_sidebars_widgets = $sidebars_widgets;
   769 	}
   691 	}
   770 
   692 
   771 	if ( is_array( $_sidebars_widgets ) ) {
   693 	if ( is_array( $_sidebars_widgets ) ) {
   772 		set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $_sidebars_widgets ) );
   694 		set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $_sidebars_widgets ) );
   773 	}
   695 	}
   774 
   696 
   775 	$old_theme  = wp_get_theme();
   697 	$nav_menu_locations = get_theme_mod( 'nav_menu_locations' );
       
   698 	update_option( 'theme_switch_menu_locations', $nav_menu_locations );
       
   699 
       
   700 	if ( func_num_args() > 1 ) {
       
   701 		$stylesheet = func_get_arg( 1 );
       
   702 	}
       
   703 
       
   704 	$old_theme = wp_get_theme();
   776 	$new_theme = wp_get_theme( $stylesheet );
   705 	$new_theme = wp_get_theme( $stylesheet );
   777 
   706 	$template  = $new_theme->get_template();
   778 	if ( func_num_args() > 1 ) {
       
   779 		$template = $stylesheet;
       
   780 		$stylesheet = func_get_arg( 1 );
       
   781 	} else {
       
   782 		$template = $new_theme->get_template();
       
   783 	}
       
   784 
   707 
   785 	update_option( 'template', $template );
   708 	update_option( 'template', $template );
   786 	update_option( 'stylesheet', $stylesheet );
   709 	update_option( 'stylesheet', $stylesheet );
   787 
   710 
   788 	if ( count( $wp_theme_directories ) > 1 ) {
   711 	if ( count( $wp_theme_directories ) > 1 ) {
   798 	update_option( 'current_theme', $new_name );
   721 	update_option( 'current_theme', $new_name );
   799 
   722 
   800 	// Migrate from the old mods_{name} option to theme_mods_{slug}.
   723 	// Migrate from the old mods_{name} option to theme_mods_{slug}.
   801 	if ( is_admin() && false === get_option( 'theme_mods_' . $stylesheet ) ) {
   724 	if ( is_admin() && false === get_option( 'theme_mods_' . $stylesheet ) ) {
   802 		$default_theme_mods = (array) get_option( 'mods_' . $new_name );
   725 		$default_theme_mods = (array) get_option( 'mods_' . $new_name );
       
   726 		if ( ! empty( $nav_menu_locations ) && empty( $default_theme_mods['nav_menu_locations'] ) ) {
       
   727 			$default_theme_mods['nav_menu_locations'] = $nav_menu_locations;
       
   728 		}
   803 		add_option( "theme_mods_$stylesheet", $default_theme_mods );
   729 		add_option( "theme_mods_$stylesheet", $default_theme_mods );
   804 	} else {
   730 	} else {
   805 		/*
   731 		/*
   806 		 * Since retrieve_widgets() is called when initializing a theme in the Customizer,
   732 		 * 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
   733 		 * we need to remove the theme mods to avoid overwriting changes made via
   808 		 * the Customizer when accessing wp-admin/widgets.php.
   734 		 * the Customizer when accessing wp-admin/widgets.php.
   809 		 */
   735 		 */
   810 		if ( 'wp_ajax_customize_save' === current_action() ) {
   736 		if ( 'wp_ajax_customize_save' === current_action() ) {
   811 			remove_theme_mod( 'sidebars_widgets' );
   737 			remove_theme_mod( 'sidebars_widgets' );
   812 		}
   738 		}
   813 	}
   739 	}
   814 
   740 
   815 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
   741 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
       
   742 
   816 	/**
   743 	/**
   817 	 * Fires after the theme is switched.
   744 	 * Fires after the theme is switched.
   818 	 *
   745 	 *
   819 	 * @since 1.5.0
   746 	 * @since 1.5.0
       
   747 	 * @since 4.5.0 Introduced the `$old_theme` parameter.
   820 	 *
   748 	 *
   821 	 * @param string   $new_name  Name of the new theme.
   749 	 * @param string   $new_name  Name of the new theme.
   822 	 * @param WP_Theme $new_theme WP_Theme instance of the new theme.
   750 	 * @param WP_Theme $new_theme WP_Theme instance of the new theme.
       
   751 	 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
   823 	 */
   752 	 */
   824 	do_action( 'switch_theme', $new_name, $new_theme );
   753 	do_action( 'switch_theme', $new_name, $new_theme, $old_theme );
   825 }
   754 }
   826 
   755 
   827 /**
   756 /**
   828  * Checks that current theme files 'index.php' and 'style.css' exists.
   757  * Checks that current theme files 'index.php' and 'style.css' exists.
   829  *
   758  *
   830  * Does not check the default theme, which is the fallback and should always exist.
   759  * Does not initially check the default theme, which is the fallback and should always exist.
       
   760  * But if it doesn't exist, it'll fall back to the latest core default theme that does exist.
   831  * Will switch theme to the fallback theme if current theme does not validate.
   761  * Will switch theme to the fallback theme if current theme does not validate.
   832  * You can use the 'validate_current_theme' filter to return false to
   762  *
       
   763  * You can use the {@see 'validate_current_theme'} filter to return false to
   833  * disable this functionality.
   764  * disable this functionality.
   834  *
   765  *
   835  * @since 1.5.0
   766  * @since 1.5.0
   836  * @see WP_DEFAULT_THEME
   767  * @see WP_DEFAULT_THEME
   837  *
   768  *
   838  * @return bool
   769  * @return bool
   839  */
   770  */
   840 function validate_current_theme() {
   771 function validate_current_theme() {
   841 	/**
   772 	/**
   842 	 * Filter whether to validate the current theme.
   773 	 * Filters whether to validate the current theme.
   843 	 *
   774 	 *
   844 	 * @since 2.7.0
   775 	 * @since 2.7.0
   845 	 *
   776 	 *
   846 	 * @param bool true Validation flag to check the current theme.
   777 	 * @param bool $validate Whether to validate the current theme. Default true.
   847 	 */
   778 	 */
   848 	if ( defined('WP_INSTALLING') || ! apply_filters( 'validate_current_theme', true ) )
   779 	if ( wp_installing() || ! apply_filters( 'validate_current_theme', true ) )
   849 		return true;
   780 		return true;
   850 
   781 
   851 	if ( get_template() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/index.php') ) {
   782 	if ( ! file_exists( get_template_directory() . '/index.php' ) ) {
       
   783 		// Invalid.
       
   784 	} elseif ( ! file_exists( get_template_directory() . '/style.css' ) ) {
       
   785 		// Invalid.
       
   786 	} elseif ( is_child_theme() && ! file_exists( get_stylesheet_directory() . '/style.css' ) ) {
       
   787 		// Invalid.
       
   788 	} else {
       
   789 		// Valid.
       
   790 		return true;
       
   791 	}
       
   792 
       
   793 	$default = wp_get_theme( WP_DEFAULT_THEME );
       
   794 	if ( $default->exists() ) {
   852 		switch_theme( WP_DEFAULT_THEME );
   795 		switch_theme( WP_DEFAULT_THEME );
   853 		return false;
   796 		return false;
   854 	}
   797 	}
   855 
   798 
   856 	if ( get_stylesheet() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/style.css') ) {
   799 	/**
   857 		switch_theme( WP_DEFAULT_THEME );
   800 	 * If we're in an invalid state but WP_DEFAULT_THEME doesn't exist,
   858 		return false;
   801 	 * switch to the latest core default theme that's installed.
   859 	}
   802 	 * If it turns out that this latest core default theme is our current
   860 
   803 	 * theme, then there's nothing we can do about that, so we have to bail,
   861 	if ( is_child_theme() && ! file_exists( get_stylesheet_directory() . '/style.css' ) ) {
   804 	 * rather than going into an infinite loop. (This is why there are
   862 		switch_theme( WP_DEFAULT_THEME );
   805 	 * checks against WP_DEFAULT_THEME above, also.) We also can't do anything
   863 		return false;
   806 	 * if it turns out there is no default theme installed. (That's `false`.)
   864 	}
   807 	 */
   865 
   808 	$default = WP_Theme::get_core_default_theme();
   866 	return true;
   809 	if ( false === $default || get_stylesheet() == $default->get_stylesheet() ) {
       
   810 		return true;
       
   811 	}
       
   812 
       
   813 	switch_theme( $default->get_stylesheet() );
       
   814 	return false;
   867 }
   815 }
   868 
   816 
   869 /**
   817 /**
   870  * Retrieve all theme modifications.
   818  * Retrieve all theme modifications.
   871  *
   819  *
   872  * @since 3.1.0
   820  * @since 3.1.0
   873  *
   821  *
   874  * @return array|null Theme modifications.
   822  * @return array|void Theme modifications.
   875  */
   823  */
   876 function get_theme_mods() {
   824 function get_theme_mods() {
   877 	$theme_slug = get_option( 'stylesheet' );
   825 	$theme_slug = get_option( 'stylesheet' );
   878 	if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) {
   826 	$mods = get_option( "theme_mods_$theme_slug" );
       
   827 	if ( false === $mods ) {
   879 		$theme_name = get_option( 'current_theme' );
   828 		$theme_name = get_option( 'current_theme' );
   880 		if ( false === $theme_name )
   829 		if ( false === $theme_name )
   881 			$theme_name = wp_get_theme()->get('Name');
   830 			$theme_name = wp_get_theme()->get('Name');
   882 		$mods = get_option( "mods_$theme_name" ); // Deprecated location.
   831 		$mods = get_option( "mods_$theme_name" ); // Deprecated location.
   883 		if ( is_admin() && false !== $mods ) {
   832 		if ( is_admin() && false !== $mods ) {
   890 
   839 
   891 /**
   840 /**
   892  * Retrieve theme modification value for the current theme.
   841  * Retrieve theme modification value for the current theme.
   893  *
   842  *
   894  * If the modification name does not exist, then the $default will be passed
   843  * If the modification name does not exist, then the $default will be passed
   895  * through {@link http://php.net/sprintf sprintf()} PHP function with the first
   844  * through {@link https://secure.php.net/sprintf sprintf()} PHP function with the first
   896  * string the template directory URI and the second string the stylesheet
   845  * string the template directory URI and the second string the stylesheet
   897  * directory URI.
   846  * directory URI.
   898  *
   847  *
   899  * @since 2.1.0
   848  * @since 2.1.0
   900  *
   849  *
   901  * @param string $name Theme modification name.
   850  * @param string      $name    Theme modification name.
   902  * @param bool|string $default
   851  * @param bool|string $default
   903  * @return string
   852  * @return string
   904  */
   853  */
   905 function get_theme_mod( $name, $default = false ) {
   854 function get_theme_mod( $name, $default = false ) {
   906 	$mods = get_theme_mods();
   855 	$mods = get_theme_mods();
   907 
   856 
   908 	if ( isset( $mods[$name] ) ) {
   857 	if ( isset( $mods[$name] ) ) {
   909 		/**
   858 		/**
   910 		 * Filter the theme modification, or 'theme_mod', value.
   859 		 * Filters the theme modification, or 'theme_mod', value.
   911 		 *
   860 		 *
   912 		 * The dynamic portion of the hook name, `$name`, refers to
   861 		 * The dynamic portion of the hook name, `$name`, refers to
   913 		 * the key name of the modification array. For example,
   862 		 * the key name of the modification array. For example,
   914 		 * 'header_textcolor', 'header_image', and so on depending
   863 		 * 'header_textcolor', 'header_image', and so on depending
   915 		 * on the theme options.
   864 		 * on the theme options.
   931 /**
   880 /**
   932  * Update theme modification value for the current theme.
   881  * Update theme modification value for the current theme.
   933  *
   882  *
   934  * @since 2.1.0
   883  * @since 2.1.0
   935  *
   884  *
   936  * @param string $name Theme modification name.
   885  * @param string $name  Theme modification name.
   937  * @param mixed  $value theme modification value.
   886  * @param mixed  $value Theme modification value.
   938  */
   887  */
   939 function set_theme_mod( $name, $value ) {
   888 function set_theme_mod( $name, $value ) {
   940 	$mods = get_theme_mods();
   889 	$mods = get_theme_mods();
   941 	$old_value = isset( $mods[ $name ] ) ? $mods[ $name ] : false;
   890 	$old_value = isset( $mods[ $name ] ) ? $mods[ $name ] : false;
   942 
   891 
   943 	/**
   892 	/**
   944 	 * Filter the theme mod value on save.
   893 	 * Filters the theme mod value on save.
   945 	 *
   894 	 *
   946 	 * The dynamic portion of the hook name, `$name`, refers to the key name of
   895 	 * The dynamic portion of the hook name, `$name`, refers to the key name of
   947 	 * the modification array. For example, 'header_textcolor', 'header_image',
   896 	 * the modification array. For example, 'header_textcolor', 'header_image',
   948 	 * and so on depending on the theme options.
   897 	 * and so on depending on the theme options.
   949 	 *
   898 	 *
   950 	 * @since 3.9.0
   899 	 * @since 3.9.0
   951 	 *
   900 	 *
   952 	 * @param string $value     The new value of the theme mod.
   901 	 * @param string $value     The new value of the theme mod.
   953 	 * @param string $old_value The current value of the theme mod.
   902 	 * @param string $old_value The current value of the theme mod.
   954 	 */
   903 	 */
   955 	$mods[ $name ] = apply_filters( "pre_set_theme_mod_$name", $value, $old_value );
   904 	$mods[ $name ] = apply_filters( "pre_set_theme_mod_{$name}", $value, $old_value );
   956 
   905 
   957 	$theme = get_option( 'stylesheet' );
   906 	$theme = get_option( 'stylesheet' );
   958 	update_option( "theme_mods_$theme", $mods );
   907 	update_option( "theme_mods_$theme", $mods );
   959 }
   908 }
   960 
   909 
   965  * be removed.
   914  * be removed.
   966  *
   915  *
   967  * @since 2.1.0
   916  * @since 2.1.0
   968  *
   917  *
   969  * @param string $name Theme modification name.
   918  * @param string $name Theme modification name.
   970  * @return null
       
   971  */
   919  */
   972 function remove_theme_mod( $name ) {
   920 function remove_theme_mod( $name ) {
   973 	$mods = get_theme_mods();
   921 	$mods = get_theme_mods();
   974 
   922 
   975 	if ( ! isset( $mods[ $name ] ) )
   923 	if ( ! isset( $mods[ $name ] ) )
   976 		return;
   924 		return;
   977 
   925 
   978 	unset( $mods[ $name ] );
   926 	unset( $mods[ $name ] );
   979 
   927 
   980 	if ( empty( $mods ) )
   928 	if ( empty( $mods ) ) {
   981 		return remove_theme_mods();
   929 		remove_theme_mods();
   982 
   930 		return;
       
   931 	}
   983 	$theme = get_option( 'stylesheet' );
   932 	$theme = get_option( 'stylesheet' );
   984 	update_option( "theme_mods_$theme", $mods );
   933 	update_option( "theme_mods_$theme", $mods );
   985 }
   934 }
   986 
   935 
   987 /**
   936 /**
   998 		$theme_name = wp_get_theme()->get('Name');
   947 		$theme_name = wp_get_theme()->get('Name');
   999 	delete_option( 'mods_' . $theme_name );
   948 	delete_option( 'mods_' . $theme_name );
  1000 }
   949 }
  1001 
   950 
  1002 /**
   951 /**
  1003  * Retrieve text color for custom header.
   952  * Retrieves the custom header text color in 3- or 6-digit hexadecimal form.
  1004  *
   953  *
  1005  * @since 2.1.0
   954  * @since 2.1.0
  1006  *
   955  *
  1007  * @return string
   956  * @return string Header text color in 3- or 6-digit hexadecimal form (minus the hash symbol).
  1008  */
   957  */
  1009 function get_header_textcolor() {
   958 function get_header_textcolor() {
  1010 	return get_theme_mod('header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
   959 	return get_theme_mod('header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
  1011 }
   960 }
  1012 
   961 
  1013 /**
   962 /**
  1014  * Display text color for custom header.
   963  * Displays the custom header text color in 3- or 6-digit hexadecimal form (minus the hash symbol).
  1015  *
   964  *
  1016  * @since 2.1.0
   965  * @since 2.1.0
  1017  */
   966  */
  1018 function header_textcolor() {
   967 function header_textcolor() {
  1019 	echo get_header_textcolor();
   968 	echo get_header_textcolor();
  1029 function display_header_text() {
   978 function display_header_text() {
  1030 	if ( ! current_theme_supports( 'custom-header', 'header-text' ) )
   979 	if ( ! current_theme_supports( 'custom-header', 'header-text' ) )
  1031 		return false;
   980 		return false;
  1032 
   981 
  1033 	$text_color = get_theme_mod( 'header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
   982 	$text_color = get_theme_mod( 'header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
  1034 	return 'blank' != $text_color;
   983 	return 'blank' !== $text_color;
  1035 }
   984 }
  1036 
   985 
  1037 /**
   986 /**
  1038  * Check whether a header image is set or not.
   987  * Check whether a header image is set or not.
  1039  *
   988  *
  1065 
  1014 
  1066 	return esc_url_raw( set_url_scheme( $url ) );
  1015 	return esc_url_raw( set_url_scheme( $url ) );
  1067 }
  1016 }
  1068 
  1017 
  1069 /**
  1018 /**
       
  1019  * Create image tag markup for a custom header image.
       
  1020  *
       
  1021  * @since 4.4.0
       
  1022  *
       
  1023  * @param array $attr Optional. Additional attributes for the image tag. Can be used
       
  1024  *                              to override the default attributes. Default empty.
       
  1025  * @return string HTML image element markup or empty string on failure.
       
  1026  */
       
  1027 function get_header_image_tag( $attr = array() ) {
       
  1028 	$header = get_custom_header();
       
  1029 	$header->url = get_header_image();
       
  1030 
       
  1031 	if ( ! $header->url ) {
       
  1032 		return '';
       
  1033 	}
       
  1034 
       
  1035 	$width = absint( $header->width );
       
  1036 	$height = absint( $header->height );
       
  1037 
       
  1038 	$attr = wp_parse_args(
       
  1039 		$attr,
       
  1040 		array(
       
  1041 			'src' => $header->url,
       
  1042 			'width' => $width,
       
  1043 			'height' => $height,
       
  1044 			'alt' => get_bloginfo( 'name' ),
       
  1045 		)
       
  1046 	);
       
  1047 
       
  1048 	// Generate 'srcset' and 'sizes' if not already present.
       
  1049 	if ( empty( $attr['srcset'] ) && ! empty( $header->attachment_id ) ) {
       
  1050 		$image_meta = get_post_meta( $header->attachment_id, '_wp_attachment_metadata', true );
       
  1051 		$size_array = array( $width, $height );
       
  1052 
       
  1053 		if ( is_array( $image_meta ) ) {
       
  1054 			$srcset = wp_calculate_image_srcset( $size_array, $header->url, $image_meta, $header->attachment_id );
       
  1055 			$sizes = ! empty( $attr['sizes'] ) ? $attr['sizes'] : wp_calculate_image_sizes( $size_array, $header->url, $image_meta, $header->attachment_id );
       
  1056 
       
  1057 			if ( $srcset && $sizes ) {
       
  1058 				$attr['srcset'] = $srcset;
       
  1059 				$attr['sizes'] = $sizes;
       
  1060 			}
       
  1061 		}
       
  1062 	}
       
  1063 
       
  1064 	$attr = array_map( 'esc_attr', $attr );
       
  1065 	$html = '<img';
       
  1066 
       
  1067 	foreach ( $attr as $name => $value ) {
       
  1068 		$html .= ' ' . $name . '="' . $value . '"';
       
  1069 	}
       
  1070 
       
  1071 	$html .= ' />';
       
  1072 
       
  1073 	/**
       
  1074 	 * Filters the markup of header images.
       
  1075 	 *
       
  1076 	 * @since 4.4.0
       
  1077 	 *
       
  1078 	 * @param string $html   The HTML image tag markup being filtered.
       
  1079 	 * @param object $header The custom header object returned by 'get_custom_header()'.
       
  1080 	 * @param array  $attr   Array of the attributes for the image tag.
       
  1081 	 */
       
  1082 	return apply_filters( 'get_header_image_tag', $html, $header, $attr );
       
  1083 }
       
  1084 
       
  1085 /**
       
  1086  * Display the image markup for a custom header image.
       
  1087  *
       
  1088  * @since 4.4.0
       
  1089  *
       
  1090  * @param array $attr Optional. Attributes for the image markup. Default empty.
       
  1091  */
       
  1092 function the_header_image_tag( $attr = array() ) {
       
  1093 	echo get_header_image_tag( $attr );
       
  1094 }
       
  1095 
       
  1096 /**
  1070  * Get random header image data from registered images in theme.
  1097  * Get random header image data from registered images in theme.
  1071  *
  1098  *
  1072  * @since 3.4.0
  1099  * @since 3.4.0
  1073  *
  1100  *
  1074  * @access private
  1101  * @access private
  1075  *
  1102  *
  1076  * @return string Path to header image
  1103  * @global array  $_wp_default_headers
  1077  */
  1104  * @staticvar object $_wp_random_header
  1078 
  1105  *
       
  1106  * @return object
       
  1107  */
  1079 function _get_random_header_data() {
  1108 function _get_random_header_data() {
  1080 	static $_wp_random_header;
  1109 	static $_wp_random_header = null;
  1081 
  1110 
  1082 	if ( empty( $_wp_random_header ) ) {
  1111 	if ( empty( $_wp_random_header ) ) {
  1083 		global $_wp_default_headers;
  1112 		global $_wp_default_headers;
  1084 		$header_image_mod = get_theme_mod( 'header_image', '' );
  1113 		$header_image_mod = get_theme_mod( 'header_image', '' );
  1085 		$headers = array();
  1114 		$headers = array();
  1111  *
  1140  *
  1112  * @since 3.2.0
  1141  * @since 3.2.0
  1113  *
  1142  *
  1114  * @return string Path to header image
  1143  * @return string Path to header image
  1115  */
  1144  */
  1116 
       
  1117 function get_random_header_image() {
  1145 function get_random_header_image() {
  1118 	$random_image = _get_random_header_data();
  1146 	$random_image = _get_random_header_data();
  1119 	if ( empty( $random_image->url ) )
  1147 	if ( empty( $random_image->url ) )
  1120 		return '';
  1148 		return '';
  1121 	return $random_image->url;
  1149 	return $random_image->url;
  1129  * is chosen, and theme turns on random headers with add_theme_support().
  1157  * is chosen, and theme turns on random headers with add_theme_support().
  1130  *
  1158  *
  1131  * @since 3.2.0
  1159  * @since 3.2.0
  1132  *
  1160  *
  1133  * @param string $type The random pool to use. any|default|uploaded
  1161  * @param string $type The random pool to use. any|default|uploaded
  1134  * @return boolean
  1162  * @return bool
  1135  */
  1163  */
  1136 function is_random_header_image( $type = 'any' ) {
  1164 function is_random_header_image( $type = 'any' ) {
  1137 	$header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
  1165 	$header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
  1138 
  1166 
  1139 	if ( 'any' == $type ) {
  1167 	if ( 'any' == $type ) {
  1178 		return array();
  1206 		return array();
  1179 
  1207 
  1180 	foreach ( (array) $headers as $header ) {
  1208 	foreach ( (array) $headers as $header ) {
  1181 		$url = esc_url_raw( wp_get_attachment_url( $header->ID ) );
  1209 		$url = esc_url_raw( wp_get_attachment_url( $header->ID ) );
  1182 		$header_data = wp_get_attachment_metadata( $header->ID );
  1210 		$header_data = wp_get_attachment_metadata( $header->ID );
  1183 		$header_index = basename($url);
  1211 		$header_index = $header->ID;
       
  1212 
  1184 		$header_images[$header_index] = array();
  1213 		$header_images[$header_index] = array();
  1185 		$header_images[$header_index]['attachment_id'] =  $header->ID;
  1214 		$header_images[$header_index]['attachment_id'] = $header->ID;
  1186 		$header_images[$header_index]['url'] =  $url;
  1215 		$header_images[$header_index]['url'] =  $url;
  1187 		$header_images[$header_index]['thumbnail_url'] =  $url;
  1216 		$header_images[$header_index]['thumbnail_url'] = $url;
       
  1217 		$header_images[$header_index]['alt_text'] = get_post_meta( $header->ID, '_wp_attachment_image_alt', true );
       
  1218 		$header_images[$header_index]['attachment_parent'] = isset( $header_data['attachment_parent'] ) ? $header_data['attachment_parent'] : '';
       
  1219 
  1188 		if ( isset( $header_data['width'] ) )
  1220 		if ( isset( $header_data['width'] ) )
  1189 			$header_images[$header_index]['width'] = $header_data['width'];
  1221 			$header_images[$header_index]['width'] = $header_data['width'];
  1190 		if ( isset( $header_data['height'] ) )
  1222 		if ( isset( $header_data['height'] ) )
  1191 			$header_images[$header_index]['height'] = $header_data['height'];
  1223 			$header_images[$header_index]['height'] = $header_data['height'];
  1192 	}
  1224 	}
  1196 
  1228 
  1197 /**
  1229 /**
  1198  * Get the header image data.
  1230  * Get the header image data.
  1199  *
  1231  *
  1200  * @since 3.4.0
  1232  * @since 3.4.0
       
  1233  *
       
  1234  * @global array $_wp_default_headers
  1201  *
  1235  *
  1202  * @return object
  1236  * @return object
  1203  */
  1237  */
  1204 function get_custom_header() {
  1238 function get_custom_header() {
  1205 	global $_wp_default_headers;
  1239 	global $_wp_default_headers;
  1229 	$default = array(
  1263 	$default = array(
  1230 		'url'           => '',
  1264 		'url'           => '',
  1231 		'thumbnail_url' => '',
  1265 		'thumbnail_url' => '',
  1232 		'width'         => get_theme_support( 'custom-header', 'width' ),
  1266 		'width'         => get_theme_support( 'custom-header', 'width' ),
  1233 		'height'        => get_theme_support( 'custom-header', 'height' ),
  1267 		'height'        => get_theme_support( 'custom-header', 'height' ),
       
  1268 		'video'         => get_theme_support( 'custom-header', 'video' ),
  1234 	);
  1269 	);
  1235 	return (object) wp_parse_args( $data, $default );
  1270 	return (object) wp_parse_args( $data, $default );
  1236 }
  1271 }
  1237 
  1272 
  1238 /**
  1273 /**
  1239  * Register a selection of default headers to be displayed by the custom header admin UI.
  1274  * Register a selection of default headers to be displayed by the custom header admin UI.
  1240  *
  1275  *
  1241  * @since 3.0.0
  1276  * @since 3.0.0
  1242  *
  1277  *
       
  1278  * @global array $_wp_default_headers
       
  1279  *
  1243  * @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys.
  1280  * @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys.
  1244  */
  1281  */
  1245 function register_default_headers( $headers ) {
  1282 function register_default_headers( $headers ) {
  1246 	global $_wp_default_headers;
  1283 	global $_wp_default_headers;
  1247 
  1284 
  1254  * This function must be called after register_default_headers() has already added the
  1291  * This function must be called after register_default_headers() has already added the
  1255  * header you want to remove.
  1292  * header you want to remove.
  1256  *
  1293  *
  1257  * @see register_default_headers()
  1294  * @see register_default_headers()
  1258  * @since 3.0.0
  1295  * @since 3.0.0
       
  1296  *
       
  1297  * @global array $_wp_default_headers
  1259  *
  1298  *
  1260  * @param string|array $header The header string id (key of array) to remove, or an array thereof.
  1299  * @param string|array $header The header string id (key of array) to remove, or an array thereof.
  1261  * @return bool|void A single header returns true on success, false on failure.
  1300  * @return bool|void A single header returns true on success, false on failure.
  1262  *                   There is currently no return value for multiple headers.
  1301  *                   There is currently no return value for multiple headers.
  1263  */
  1302  */
  1272 		return false;
  1311 		return false;
  1273 	}
  1312 	}
  1274 }
  1313 }
  1275 
  1314 
  1276 /**
  1315 /**
       
  1316  * Check whether a header video is set or not.
       
  1317  *
       
  1318  * @since 4.7.0
       
  1319  *
       
  1320  * @see get_header_video_url()
       
  1321  *
       
  1322  * @return bool Whether a header video is set or not.
       
  1323  */
       
  1324 function has_header_video() {
       
  1325 	return (bool) get_header_video_url();
       
  1326 }
       
  1327 
       
  1328 /**
       
  1329  * Retrieve header video URL for custom header.
       
  1330  *
       
  1331  * Uses a local video if present, or falls back to an external video.
       
  1332  *
       
  1333  * @since 4.7.0
       
  1334  *
       
  1335  * @return string|false Header video URL or false if there is no video.
       
  1336  */
       
  1337 function get_header_video_url() {
       
  1338 	$id = absint( get_theme_mod( 'header_video' ) );
       
  1339 	$url = esc_url( get_theme_mod( 'external_header_video' ) );
       
  1340 
       
  1341 	if ( $id ) {
       
  1342 		// Get the file URL from the attachment ID.
       
  1343 		$url = wp_get_attachment_url( $id );
       
  1344 	}
       
  1345 
       
  1346 	/**
       
  1347 	 * Filters the header video URL.
       
  1348 	 *
       
  1349 	 * @since 4.7.3
       
  1350 	 *
       
  1351 	 * @param string $url Header video URL, if available.
       
  1352 	 */
       
  1353 	$url = apply_filters( 'get_header_video_url', $url );
       
  1354 
       
  1355 	if ( ! $id && ! $url ) {
       
  1356 		return false;
       
  1357 	}
       
  1358 
       
  1359 	return esc_url_raw( set_url_scheme( $url ) );
       
  1360 }
       
  1361 
       
  1362 /**
       
  1363  * Display header video URL.
       
  1364  *
       
  1365  * @since 4.7.0
       
  1366  */
       
  1367 function the_header_video_url() {
       
  1368 	$video = get_header_video_url();
       
  1369 	if ( $video ) {
       
  1370 		echo esc_url( $video );
       
  1371 	}
       
  1372 }
       
  1373 
       
  1374 /**
       
  1375  * Retrieve header video settings.
       
  1376  *
       
  1377  * @since 4.7.0
       
  1378  *
       
  1379  * @return array
       
  1380  */
       
  1381 function get_header_video_settings() {
       
  1382 	$header     = get_custom_header();
       
  1383 	$video_url  = get_header_video_url();
       
  1384 	$video_type = wp_check_filetype( $video_url, wp_get_mime_types() );
       
  1385 
       
  1386 	$settings = array(
       
  1387 		'mimeType'  => '',
       
  1388 		'posterUrl' => get_header_image(),
       
  1389 		'videoUrl'  => $video_url,
       
  1390 		'width'     => absint( $header->width ),
       
  1391 		'height'    => absint( $header->height ),
       
  1392 		'minWidth'  => 900,
       
  1393 		'minHeight' => 500,
       
  1394 		'l10n'      => array(
       
  1395 			'pause'      => __( 'Pause' ),
       
  1396 			'play'       => __( 'Play' ),
       
  1397 			'pauseSpeak' => __( 'Video is paused.'),
       
  1398 			'playSpeak'  => __( 'Video is playing.'),
       
  1399 		),
       
  1400 	);
       
  1401 
       
  1402 	if ( preg_match( '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#', $video_url ) ) {
       
  1403 		$settings['mimeType'] = 'video/x-youtube';
       
  1404 	} elseif ( ! empty( $video_type['type'] ) ) {
       
  1405 		$settings['mimeType'] = $video_type['type'];
       
  1406 	}
       
  1407 
       
  1408 	return apply_filters( 'header_video_settings', $settings );
       
  1409 }
       
  1410 
       
  1411 /**
       
  1412  * Check whether a custom header is set or not.
       
  1413  *
       
  1414  * @since 4.7.0
       
  1415  *
       
  1416  * @return bool True if a custom header is set. False if not.
       
  1417  */
       
  1418 function has_custom_header() {
       
  1419 	if ( has_header_image() || ( has_header_video() && is_header_video_active() ) ) {
       
  1420 		return true;
       
  1421 	}
       
  1422 
       
  1423 	return false;
       
  1424 }
       
  1425 
       
  1426 /**
       
  1427  * Checks whether the custom header video is eligible to show on the current page.
       
  1428  *
       
  1429  * @since 4.7.0
       
  1430  *
       
  1431  * @return bool True if the custom header video should be shown. False if not.
       
  1432  */
       
  1433 function is_header_video_active() {
       
  1434 	if ( ! get_theme_support( 'custom-header', 'video' ) ) {
       
  1435 		return false;
       
  1436 	}
       
  1437 
       
  1438 	$video_active_cb = get_theme_support( 'custom-header', 'video-active-callback' );
       
  1439 
       
  1440 	if ( empty( $video_active_cb ) || ! is_callable( $video_active_cb ) ) {
       
  1441 		$show_video = true;
       
  1442 	} else {
       
  1443 		$show_video = call_user_func( $video_active_cb );
       
  1444 	}
       
  1445 
       
  1446 	/**
       
  1447 	 * Modify whether the custom header video is eligible to show on the current page.
       
  1448 	 *
       
  1449 	 * @since 4.7.0
       
  1450 	 *
       
  1451 	 * @param bool $show_video Whether the custom header video should be shown. Returns the value
       
  1452 	 *                         of the theme setting for the `custom-header`'s `video-active-callback`.
       
  1453 	 *                         If no callback is set, the default value is that of `is_front_page()`.
       
  1454 	 */
       
  1455 	return apply_filters( 'is_header_video_active', $show_video );
       
  1456 }
       
  1457 
       
  1458 /**
       
  1459  * Retrieve the markup for a custom header.
       
  1460  *
       
  1461  * The container div will always be returned in the Customizer preview.
       
  1462  *
       
  1463  * @since 4.7.0
       
  1464  *
       
  1465  * @return string The markup for a custom header on success.
       
  1466  */
       
  1467 function get_custom_header_markup() {
       
  1468 	if ( ! has_custom_header() && ! is_customize_preview() ) {
       
  1469 		return '';
       
  1470 	}
       
  1471 
       
  1472 	return sprintf(
       
  1473 		'<div id="wp-custom-header" class="wp-custom-header">%s</div>',
       
  1474 		get_header_image_tag()
       
  1475 	);
       
  1476 }
       
  1477 
       
  1478 /**
       
  1479  * Print the markup for a custom header.
       
  1480  *
       
  1481  * A container div will always be printed in the Customizer preview.
       
  1482  *
       
  1483  * @since 4.7.0
       
  1484  */
       
  1485 function the_custom_header_markup() {
       
  1486 	$custom_header = get_custom_header_markup();
       
  1487 	if ( empty( $custom_header ) ) {
       
  1488 		return;
       
  1489 	}
       
  1490 
       
  1491 	echo $custom_header;
       
  1492 
       
  1493 	if ( is_header_video_active() && ( has_header_video() || is_customize_preview() ) ) {
       
  1494 		wp_enqueue_script( 'wp-custom-header' );
       
  1495 		wp_localize_script( 'wp-custom-header', '_wpCustomHeaderSettings', get_header_video_settings() );
       
  1496 	}
       
  1497 }
       
  1498 
       
  1499 /**
  1277  * Retrieve background image for custom background.
  1500  * Retrieve background image for custom background.
  1278  *
  1501  *
  1279  * @since 3.0.0
  1502  * @since 3.0.0
  1280  *
  1503  *
  1281  * @return string
  1504  * @return string
  1315 
  1538 
  1316 /**
  1539 /**
  1317  * Default custom background callback.
  1540  * Default custom background callback.
  1318  *
  1541  *
  1319  * @since 3.0.0
  1542  * @since 3.0.0
  1320  * @access protected
       
  1321  */
  1543  */
  1322 function _custom_background_cb() {
  1544 function _custom_background_cb() {
  1323 	// $background is the saved custom image, or the default image.
  1545 	// $background is the saved custom image, or the default image.
  1324 	$background = set_url_scheme( get_background_image() );
  1546 	$background = set_url_scheme( get_background_image() );
  1325 
  1547 
  1329 
  1551 
  1330 	if ( $color === get_theme_support( 'custom-background', 'default-color' ) ) {
  1552 	if ( $color === get_theme_support( 'custom-background', 'default-color' ) ) {
  1331 		$color = false;
  1553 		$color = false;
  1332 	}
  1554 	}
  1333 
  1555 
  1334 	if ( ! $background && ! $color )
  1556 	if ( ! $background && ! $color ) {
       
  1557 		if ( is_customize_preview() ) {
       
  1558 			echo '<style type="text/css" id="custom-background-css"></style>';
       
  1559 		}
  1335 		return;
  1560 		return;
       
  1561 	}
  1336 
  1562 
  1337 	$style = $color ? "background-color: #$color;" : '';
  1563 	$style = $color ? "background-color: #$color;" : '';
  1338 
  1564 
  1339 	if ( $background ) {
  1565 	if ( $background ) {
  1340 		$image = " background-image: url('$background');";
  1566 		$image = ' background-image: url("' . esc_url_raw( $background ) . '");';
  1341 
  1567 
       
  1568 		// Background Position.
       
  1569 		$position_x = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
       
  1570 		$position_y = get_theme_mod( 'background_position_y', get_theme_support( 'custom-background', 'default-position-y' ) );
       
  1571 
       
  1572 		if ( ! in_array( $position_x, array( 'left', 'center', 'right' ), true ) ) {
       
  1573 			$position_x = 'left';
       
  1574 		}
       
  1575 
       
  1576 		if ( ! in_array( $position_y, array( 'top', 'center', 'bottom' ), true ) ) {
       
  1577 			$position_y = 'top';
       
  1578 		}
       
  1579 
       
  1580 		$position = " background-position: $position_x $position_y;";
       
  1581 
       
  1582 		// Background Size.
       
  1583 		$size = get_theme_mod( 'background_size', get_theme_support( 'custom-background', 'default-size' ) );
       
  1584 
       
  1585 		if ( ! in_array( $size, array( 'auto', 'contain', 'cover' ), true ) ) {
       
  1586 			$size = 'auto';
       
  1587 		}
       
  1588 
       
  1589 		$size = " background-size: $size;";
       
  1590 
       
  1591 		// Background Repeat.
  1342 		$repeat = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) );
  1592 		$repeat = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) );
  1343 		if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
  1593 
       
  1594 		if ( ! in_array( $repeat, array( 'repeat-x', 'repeat-y', 'repeat', 'no-repeat' ), true ) ) {
  1344 			$repeat = 'repeat';
  1595 			$repeat = 'repeat';
       
  1596 		}
       
  1597 
  1345 		$repeat = " background-repeat: $repeat;";
  1598 		$repeat = " background-repeat: $repeat;";
  1346 
  1599 
  1347 		$position = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
  1600 		// Background Scroll.
  1348 		if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) )
       
  1349 			$position = 'left';
       
  1350 		$position = " background-position: top $position;";
       
  1351 
       
  1352 		$attachment = get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) );
  1601 		$attachment = get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) );
  1353 		if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) )
  1602 
       
  1603 		if ( 'fixed' !== $attachment ) {
  1354 			$attachment = 'scroll';
  1604 			$attachment = 'scroll';
       
  1605 		}
       
  1606 
  1355 		$attachment = " background-attachment: $attachment;";
  1607 		$attachment = " background-attachment: $attachment;";
  1356 
  1608 
  1357 		$style .= $image . $repeat . $position . $attachment;
  1609 		$style .= $image . $position . $size . $repeat . $attachment;
  1358 	}
  1610 	}
  1359 ?>
  1611 ?>
  1360 <style type="text/css" id="custom-background-css">
  1612 <style type="text/css" id="custom-background-css">
  1361 body.custom-background { <?php echo trim( $style ); ?> }
  1613 body.custom-background { <?php echo trim( $style ); ?> }
  1362 </style>
  1614 </style>
  1363 <?php
  1615 <?php
  1364 }
  1616 }
  1365 
  1617 
  1366 /**
  1618 /**
       
  1619  * Render the Custom CSS style element.
       
  1620  *
       
  1621  * @since 4.7.0
       
  1622  */
       
  1623 function wp_custom_css_cb() {
       
  1624 	$styles = wp_get_custom_css();
       
  1625 	if ( $styles || is_customize_preview() ) : ?>
       
  1626 		<style type="text/css" id="wp-custom-css">
       
  1627 			<?php echo strip_tags( $styles ); // Note that esc_html() cannot be used because `div &gt; span` is not interpreted properly. ?>
       
  1628 		</style>
       
  1629 	<?php endif;
       
  1630 }
       
  1631 
       
  1632 /**
       
  1633  * Fetch the `custom_css` post for a given theme.
       
  1634  *
       
  1635  * @since 4.7.0
       
  1636  *
       
  1637  * @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the current theme.
       
  1638  * @return WP_Post|null The custom_css post or null if none exists.
       
  1639  */
       
  1640 function wp_get_custom_css_post( $stylesheet = '' ) {
       
  1641 	if ( empty( $stylesheet ) ) {
       
  1642 		$stylesheet = get_stylesheet();
       
  1643 	}
       
  1644 
       
  1645 	$custom_css_query_vars = array(
       
  1646 		'post_type'              => 'custom_css',
       
  1647 		'post_status'            => get_post_stati(),
       
  1648 		'name'                   => sanitize_title( $stylesheet ),
       
  1649 		'posts_per_page'         => 1,
       
  1650 		'no_found_rows'          => true,
       
  1651 		'cache_results'          => true,
       
  1652 		'update_post_meta_cache' => false,
       
  1653 		'update_post_term_cache' => false,
       
  1654 		'lazy_load_term_meta'    => false,
       
  1655 	);
       
  1656 
       
  1657 	$post = null;
       
  1658 	if ( get_stylesheet() === $stylesheet ) {
       
  1659 		$post_id = get_theme_mod( 'custom_css_post_id' );
       
  1660 
       
  1661 		if ( $post_id > 0 && get_post( $post_id ) ) {
       
  1662 			$post = get_post( $post_id );
       
  1663 		}
       
  1664 
       
  1665 		// `-1` indicates no post exists; no query necessary.
       
  1666 		if ( ! $post && -1 !== $post_id ) {
       
  1667 			$query = new WP_Query( $custom_css_query_vars );
       
  1668 			$post = $query->post;
       
  1669 			/*
       
  1670 			 * Cache the lookup. See wp_update_custom_css_post().
       
  1671 			 * @todo This should get cleared if a custom_css post is added/removed.
       
  1672 			 */
       
  1673 			set_theme_mod( 'custom_css_post_id', $post ? $post->ID : -1 );
       
  1674 		}
       
  1675 	} else {
       
  1676 		$query = new WP_Query( $custom_css_query_vars );
       
  1677 		$post = $query->post;
       
  1678 	}
       
  1679 
       
  1680 	return $post;
       
  1681 }
       
  1682 
       
  1683 /**
       
  1684  * Fetch the saved Custom CSS content for rendering.
       
  1685  *
       
  1686  * @since 4.7.0
       
  1687  *
       
  1688  * @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the current theme.
       
  1689  * @return string The Custom CSS Post content.
       
  1690  */
       
  1691 function wp_get_custom_css( $stylesheet = '' ) {
       
  1692 	$css = '';
       
  1693 
       
  1694 	if ( empty( $stylesheet ) ) {
       
  1695 		$stylesheet = get_stylesheet();
       
  1696 	}
       
  1697 
       
  1698 	$post = wp_get_custom_css_post( $stylesheet );
       
  1699 	if ( $post ) {
       
  1700 		$css = $post->post_content;
       
  1701 	}
       
  1702 
       
  1703 	/**
       
  1704 	 * Filters the Custom CSS Output into the <head>.
       
  1705 	 *
       
  1706 	 * @since 4.7.0
       
  1707 	 *
       
  1708 	 * @param string $css        CSS pulled in from the Custom CSS CPT.
       
  1709 	 * @param string $stylesheet The theme stylesheet name.
       
  1710 	 */
       
  1711 	$css = apply_filters( 'wp_get_custom_css', $css, $stylesheet );
       
  1712 
       
  1713 	return $css;
       
  1714 }
       
  1715 
       
  1716 /**
       
  1717  * Update the `custom_css` post for a given theme.
       
  1718  *
       
  1719  * Inserts a `custom_css` post when one doesn't yet exist.
       
  1720  *
       
  1721  * @since 4.7.0
       
  1722  *
       
  1723  * @param string $css CSS, stored in `post_content`.
       
  1724  * @param array  $args {
       
  1725  *     Args.
       
  1726  *
       
  1727  *     @type string $preprocessed Pre-processed CSS, stored in `post_content_filtered`. Normally empty string. Optional.
       
  1728  *     @type string $stylesheet   Stylesheet (child theme) to update. Optional, defaults to current theme/stylesheet.
       
  1729  * }
       
  1730  * @return WP_Post|WP_Error Post on success, error on failure.
       
  1731  */
       
  1732 function wp_update_custom_css_post( $css, $args = array() ) {
       
  1733 	$args = wp_parse_args( $args, array(
       
  1734 		'preprocessed' => '',
       
  1735 		'stylesheet' => get_stylesheet(),
       
  1736 	) );
       
  1737 
       
  1738 	$data = array(
       
  1739 		'css' => $css,
       
  1740 		'preprocessed' => $args['preprocessed'],
       
  1741 	);
       
  1742 
       
  1743 	/**
       
  1744 	 * Filters the `css` (`post_content`) and `preprocessed` (`post_content_filtered`) args for a `custom_css` post being updated.
       
  1745 	 *
       
  1746 	 * This filter can be used by plugin that offer CSS pre-processors, to store the original
       
  1747 	 * pre-processed CSS in `post_content_filtered` and then store processed CSS in `post_content`.
       
  1748 	 * When used in this way, the `post_content_filtered` should be supplied as the setting value
       
  1749 	 * instead of `post_content` via a the `customize_value_custom_css` filter, for example:
       
  1750 	 *
       
  1751 	 * <code>
       
  1752 	 * add_filter( 'customize_value_custom_css', function( $value, $setting ) {
       
  1753 	 *     $post = wp_get_custom_css_post( $setting->stylesheet );
       
  1754 	 *     if ( $post && ! empty( $post->post_content_filtered ) ) {
       
  1755 	 *         $css = $post->post_content_filtered;
       
  1756 	 *     }
       
  1757 	 *     return $css;
       
  1758 	 * }, 10, 2 );
       
  1759 	 * </code>
       
  1760 	 *
       
  1761 	 * @since 4.7.0
       
  1762 	 * @param array $data {
       
  1763 	 *     Custom CSS data.
       
  1764 	 *
       
  1765 	 *     @type string $css          CSS stored in `post_content`.
       
  1766 	 *     @type string $preprocessed Pre-processed CSS stored in `post_content_filtered`. Normally empty string.
       
  1767 	 * }
       
  1768 	 * @param array $args {
       
  1769 	 *     The args passed into `wp_update_custom_css_post()` merged with defaults.
       
  1770 	 *
       
  1771 	 *     @type string $css          The original CSS passed in to be updated.
       
  1772 	 *     @type string $preprocessed The original preprocessed CSS passed in to be updated.
       
  1773 	 *     @type string $stylesheet   The stylesheet (theme) being updated.
       
  1774 	 * }
       
  1775 	 */
       
  1776 	$data = apply_filters( 'update_custom_css_data', $data, array_merge( $args, compact( 'css' ) ) );
       
  1777 
       
  1778 	$post_data = array(
       
  1779 		'post_title' => $args['stylesheet'],
       
  1780 		'post_name' => sanitize_title( $args['stylesheet'] ),
       
  1781 		'post_type' => 'custom_css',
       
  1782 		'post_status' => 'publish',
       
  1783 		'post_content' => $data['css'],
       
  1784 		'post_content_filtered' => $data['preprocessed'],
       
  1785 	);
       
  1786 
       
  1787 	// Update post if it already exists, otherwise create a new one.
       
  1788 	$post = wp_get_custom_css_post( $args['stylesheet'] );
       
  1789 	if ( $post ) {
       
  1790 		$post_data['ID'] = $post->ID;
       
  1791 		$r = wp_update_post( wp_slash( $post_data ), true );
       
  1792 	} else {
       
  1793 		$r = wp_insert_post( wp_slash( $post_data ), true );
       
  1794 
       
  1795 		if ( ! is_wp_error( $r ) ) {
       
  1796 			if ( get_stylesheet() === $args['stylesheet'] ) {
       
  1797 				set_theme_mod( 'custom_css_post_id', $r );
       
  1798 			}
       
  1799 
       
  1800 			// Trigger creation of a revision. This should be removed once #30854 is resolved.
       
  1801 			if ( 0 === count( wp_get_post_revisions( $r ) ) ) {
       
  1802 				wp_save_post_revision( $r );
       
  1803 			}
       
  1804 		}
       
  1805 	}
       
  1806 
       
  1807 	if ( is_wp_error( $r ) ) {
       
  1808 		return $r;
       
  1809 	}
       
  1810 	return get_post( $r );
       
  1811 }
       
  1812 
       
  1813 /**
  1367  * Add callback for custom TinyMCE editor stylesheets.
  1814  * Add callback for custom TinyMCE editor stylesheets.
  1368  *
  1815  *
  1369  * The parameter $stylesheet is the name of the stylesheet, relative to
  1816  * The parameter $stylesheet is the name of the stylesheet, relative to
  1370  * the theme root. It also accepts an array of stylesheets.
  1817  * the theme root. It also accepts an array of stylesheets.
  1371  * It is optional and defaults to 'editor-style.css'.
  1818  * It is optional and defaults to 'editor-style.css'.
  1378  * Since version 3.4 the TinyMCE body has .rtl CSS class.
  1825  * Since version 3.4 the TinyMCE body has .rtl CSS class.
  1379  * It is a better option to use that class and add any RTL styles to the main stylesheet.
  1826  * It is a better option to use that class and add any RTL styles to the main stylesheet.
  1380  *
  1827  *
  1381  * @since 3.0.0
  1828  * @since 3.0.0
  1382  *
  1829  *
       
  1830  * @global array $editor_styles
       
  1831  *
  1383  * @param array|string $stylesheet Optional. Stylesheet name or array thereof, relative to theme root.
  1832  * @param array|string $stylesheet Optional. Stylesheet name or array thereof, relative to theme root.
  1384  * 	Defaults to 'editor-style.css'
  1833  * 	                               Defaults to 'editor-style.css'
  1385  */
  1834  */
  1386 function add_editor_style( $stylesheet = 'editor-style.css' ) {
  1835 function add_editor_style( $stylesheet = 'editor-style.css' ) {
  1387 
       
  1388 	add_theme_support( 'editor-style' );
  1836 	add_theme_support( 'editor-style' );
  1389 
  1837 
  1390 	if ( ! is_admin() )
  1838 	if ( ! is_admin() )
  1391 		return;
  1839 		return;
  1392 
  1840 
  1403 
  1851 
  1404 /**
  1852 /**
  1405  * Removes all visual editor stylesheets.
  1853  * Removes all visual editor stylesheets.
  1406  *
  1854  *
  1407  * @since 3.1.0
  1855  * @since 3.1.0
       
  1856  *
       
  1857  * @global array $editor_styles
  1408  *
  1858  *
  1409  * @return bool True on success, false if there were no stylesheets to remove.
  1859  * @return bool True on success, false if there were no stylesheets to remove.
  1410  */
  1860  */
  1411 function remove_editor_styles() {
  1861 function remove_editor_styles() {
  1412 	if ( ! current_theme_supports( 'editor-style' ) )
  1862 	if ( ! current_theme_supports( 'editor-style' ) )
  1420 /**
  1870 /**
  1421  * Retrieve any registered editor stylesheets
  1871  * Retrieve any registered editor stylesheets
  1422  *
  1872  *
  1423  * @since 4.0.0
  1873  * @since 4.0.0
  1424  *
  1874  *
  1425  * @global $editor_styles Registered editor stylesheets
  1875  * @global array $editor_styles Registered editor stylesheets
  1426  *
  1876  *
  1427  * @return array If registered, a list of editor stylesheet URLs.
  1877  * @return array If registered, a list of editor stylesheet URLs.
  1428  */
  1878  */
  1429 function get_editor_stylesheets() {
  1879 function get_editor_stylesheets() {
  1430 	$stylesheets = array();
  1880 	$stylesheets = array();
  1460 			if ( $file && file_exists( "$style_dir/$file" ) ) {
  1910 			if ( $file && file_exists( "$style_dir/$file" ) ) {
  1461 				$stylesheets[] = "$style_uri/$file";
  1911 				$stylesheets[] = "$style_uri/$file";
  1462 			}
  1912 			}
  1463 		}
  1913 		}
  1464 	}
  1914 	}
  1465 	return $stylesheets;
  1915 
  1466 }
  1916 	/**
  1467 
  1917 	 * Filters the array of stylesheets applied to the editor.
  1468 /**
  1918 	 *
  1469  * Allows a theme to register its support of a certain feature
  1919 	 * @since 4.3.0
       
  1920 	 *
       
  1921 	 * @param array $stylesheets Array of stylesheets to be applied to the editor.
       
  1922 	 */
       
  1923 	return apply_filters( 'editor_stylesheets', $stylesheets );
       
  1924 }
       
  1925 
       
  1926 /**
       
  1927  * Expand a theme's starter content configuration using core-provided data.
       
  1928  *
       
  1929  * @since 4.7.0
       
  1930  *
       
  1931  * @return array Array of starter content.
       
  1932  */
       
  1933 function get_theme_starter_content() {
       
  1934 	$theme_support = get_theme_support( 'starter-content' );
       
  1935 	if ( is_array( $theme_support ) && ! empty( $theme_support[0] ) && is_array( $theme_support[0] ) ) {
       
  1936 		$config = $theme_support[0];
       
  1937 	} else {
       
  1938 		$config = array();
       
  1939 	}
       
  1940 
       
  1941 	$core_content = array(
       
  1942 		'widgets' => array(
       
  1943 			'text_business_info' => array( 'text', array(
       
  1944 				'title' => _x( 'Find Us', 'Theme starter content' ),
       
  1945 				'text' => join( '', array(
       
  1946 					'<strong>' . _x( 'Address', 'Theme starter content' ) . "</strong>\n",
       
  1947 					_x( '123 Main Street', 'Theme starter content' ) . "\n" . _x( 'New York, NY 10001', 'Theme starter content' ) . "\n\n",
       
  1948 					'<strong>' . _x( 'Hours', 'Theme starter content' ) . "</strong>\n",
       
  1949 					_x( 'Monday&mdash;Friday: 9:00AM&ndash;5:00PM', 'Theme starter content' ) . "\n" . _x( 'Saturday &amp; Sunday: 11:00AM&ndash;3:00PM', 'Theme starter content' )
       
  1950 				) ),
       
  1951 				'filter' => true,
       
  1952 				'visual' => true,
       
  1953 			) ),
       
  1954 			'text_about' => array( 'text', array(
       
  1955 				'title' => _x( 'About This Site', 'Theme starter content' ),
       
  1956 				'text' => _x( 'This may be a good place to introduce yourself and your site or include some credits.', 'Theme starter content' ),
       
  1957 				'filter' => true,
       
  1958 				'visual' => true,
       
  1959 			) ),
       
  1960 			'archives' => array( 'archives', array(
       
  1961 				'title' => _x( 'Archives', 'Theme starter content' ),
       
  1962 			) ),
       
  1963 			'calendar' => array( 'calendar', array(
       
  1964 				'title' => _x( 'Calendar', 'Theme starter content' ),
       
  1965 			) ),
       
  1966 			'categories' => array( 'categories', array(
       
  1967 				'title' => _x( 'Categories', 'Theme starter content' ),
       
  1968 			) ),
       
  1969 			'meta' => array( 'meta', array(
       
  1970 				'title' => _x( 'Meta', 'Theme starter content' ),
       
  1971 			) ),
       
  1972 			'recent-comments' => array( 'recent-comments', array(
       
  1973 				'title' => _x( 'Recent Comments', 'Theme starter content' ),
       
  1974 			) ),
       
  1975 			'recent-posts' => array( 'recent-posts', array(
       
  1976 				'title' => _x( 'Recent Posts', 'Theme starter content' ),
       
  1977 			) ),
       
  1978 			'search' => array( 'search', array(
       
  1979 				'title' => _x( 'Search', 'Theme starter content' ),
       
  1980 			) ),
       
  1981 		),
       
  1982 		'nav_menus' => array(
       
  1983 			'link_home' => array(
       
  1984 				'type' => 'custom',
       
  1985 				'title' => _x( 'Home', 'Theme starter content' ),
       
  1986 				'url' => home_url( '/' ),
       
  1987 			),
       
  1988 			'page_home' => array( // Deprecated in favor of link_home.
       
  1989 				'type' => 'post_type',
       
  1990 				'object' => 'page',
       
  1991 				'object_id' => '{{home}}',
       
  1992 			),
       
  1993 			'page_about' => array(
       
  1994 				'type' => 'post_type',
       
  1995 				'object' => 'page',
       
  1996 				'object_id' => '{{about}}',
       
  1997 			),
       
  1998 			'page_blog' => array(
       
  1999 				'type' => 'post_type',
       
  2000 				'object' => 'page',
       
  2001 				'object_id' => '{{blog}}',
       
  2002 			),
       
  2003 			'page_news' => array(
       
  2004 				'type' => 'post_type',
       
  2005 				'object' => 'page',
       
  2006 				'object_id' => '{{news}}',
       
  2007 			),
       
  2008 			'page_contact' => array(
       
  2009 				'type' => 'post_type',
       
  2010 				'object' => 'page',
       
  2011 				'object_id' => '{{contact}}',
       
  2012 			),
       
  2013 
       
  2014 			'link_email' => array(
       
  2015 				'title' => _x( 'Email', 'Theme starter content' ),
       
  2016 				'url' => 'mailto:wordpress@example.com',
       
  2017 			),
       
  2018 			'link_facebook' => array(
       
  2019 				'title' => _x( 'Facebook', 'Theme starter content' ),
       
  2020 				'url' => 'https://www.facebook.com/wordpress',
       
  2021 			),
       
  2022 			'link_foursquare' => array(
       
  2023 				'title' => _x( 'Foursquare', 'Theme starter content' ),
       
  2024 				'url' => 'https://foursquare.com/',
       
  2025 			),
       
  2026 			'link_github' => array(
       
  2027 				'title' => _x( 'GitHub', 'Theme starter content' ),
       
  2028 				'url' => 'https://github.com/wordpress/',
       
  2029 			),
       
  2030 			'link_instagram' => array(
       
  2031 				'title' => _x( 'Instagram', 'Theme starter content' ),
       
  2032 				'url' => 'https://www.instagram.com/explore/tags/wordcamp/',
       
  2033 			),
       
  2034 			'link_linkedin' => array(
       
  2035 				'title' => _x( 'LinkedIn', 'Theme starter content' ),
       
  2036 				'url' => 'https://www.linkedin.com/company/1089783',
       
  2037 			),
       
  2038 			'link_pinterest' => array(
       
  2039 				'title' => _x( 'Pinterest', 'Theme starter content' ),
       
  2040 				'url' => 'https://www.pinterest.com/',
       
  2041 			),
       
  2042 			'link_twitter' => array(
       
  2043 				'title' => _x( 'Twitter', 'Theme starter content' ),
       
  2044 				'url' => 'https://twitter.com/wordpress',
       
  2045 			),
       
  2046 			'link_yelp' => array(
       
  2047 				'title' => _x( 'Yelp', 'Theme starter content' ),
       
  2048 				'url' => 'https://www.yelp.com',
       
  2049 			),
       
  2050 			'link_youtube' => array(
       
  2051 				'title' => _x( 'YouTube', 'Theme starter content' ),
       
  2052 				'url' => 'https://www.youtube.com/channel/UCdof4Ju7amm1chz1gi1T2ZA',
       
  2053 			),
       
  2054 		),
       
  2055 		'posts' => array(
       
  2056 			'home' => array(
       
  2057 				'post_type' => 'page',
       
  2058 				'post_title' => _x( 'Home', 'Theme starter content' ),
       
  2059 				'post_content' => _x( 'Welcome to your site! This is your homepage, which is what most visitors will see when they come to your site for the first time.', 'Theme starter content' ),
       
  2060 			),
       
  2061 			'about' => array(
       
  2062 				'post_type' => 'page',
       
  2063 				'post_title' => _x( 'About', 'Theme starter content' ),
       
  2064 				'post_content' => _x( 'You might be an artist who would like to introduce yourself and your work here or maybe you&rsquo;re a business with a mission to describe.', 'Theme starter content' ),
       
  2065 			),
       
  2066 			'contact' => array(
       
  2067 				'post_type' => 'page',
       
  2068 				'post_title' => _x( 'Contact', 'Theme starter content' ),
       
  2069 				'post_content' => _x( 'This is a page with some basic contact information, such as an address and phone number. You might also try a plugin to add a contact form.', 'Theme starter content' ),
       
  2070 			),
       
  2071 			'blog' => array(
       
  2072 				'post_type' => 'page',
       
  2073 				'post_title' => _x( 'Blog', 'Theme starter content' ),
       
  2074 			),
       
  2075 			'news' => array(
       
  2076 				'post_type' => 'page',
       
  2077 				'post_title' => _x( 'News', 'Theme starter content' ),
       
  2078 			),
       
  2079 
       
  2080 			'homepage-section' => array(
       
  2081 				'post_type' => 'page',
       
  2082 				'post_title' => _x( 'A homepage section', 'Theme starter content' ),
       
  2083 				'post_content' => _x( 'This is an example of a homepage section. Homepage sections can be any page other than the homepage itself, including the page that shows your latest blog posts.', 'Theme starter content' ),
       
  2084 			),
       
  2085 		),
       
  2086 	);
       
  2087 
       
  2088 	$content = array();
       
  2089 
       
  2090 	foreach ( $config as $type => $args ) {
       
  2091 		switch( $type ) {
       
  2092 			// Use options and theme_mods as-is.
       
  2093 			case 'options' :
       
  2094 			case 'theme_mods' :
       
  2095 				$content[ $type ] = $config[ $type ];
       
  2096 				break;
       
  2097 
       
  2098 			// Widgets are grouped into sidebars.
       
  2099 			case 'widgets' :
       
  2100 				foreach ( $config[ $type ] as $sidebar_id => $widgets ) {
       
  2101 					foreach ( $widgets as $id => $widget ) {
       
  2102 						if ( is_array( $widget ) ) {
       
  2103 
       
  2104 							// Item extends core content.
       
  2105 							if ( ! empty( $core_content[ $type ][ $id ] ) ) {
       
  2106 								$widget = array(
       
  2107 									$core_content[ $type ][ $id ][0],
       
  2108 									array_merge( $core_content[ $type ][ $id ][1], $widget ),
       
  2109 								);
       
  2110 							}
       
  2111 
       
  2112 							$content[ $type ][ $sidebar_id ][] = $widget;
       
  2113 						} elseif ( is_string( $widget ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $widget ] ) ) {
       
  2114 							$content[ $type ][ $sidebar_id ][] = $core_content[ $type ][ $widget ];
       
  2115 						}
       
  2116 					}
       
  2117 				}
       
  2118 				break;
       
  2119 
       
  2120 			// And nav menu items are grouped into nav menus.
       
  2121 			case 'nav_menus' :
       
  2122 				foreach ( $config[ $type ] as $nav_menu_location => $nav_menu ) {
       
  2123 
       
  2124 					// Ensure nav menus get a name.
       
  2125 					if ( empty( $nav_menu['name'] ) ) {
       
  2126 						$nav_menu['name'] = $nav_menu_location;
       
  2127 					}
       
  2128 
       
  2129 					$content[ $type ][ $nav_menu_location ]['name'] = $nav_menu['name'];
       
  2130 
       
  2131 					foreach ( $nav_menu['items'] as $id => $nav_menu_item ) {
       
  2132 						if ( is_array( $nav_menu_item ) ) {
       
  2133 
       
  2134 							// Item extends core content.
       
  2135 							if ( ! empty( $core_content[ $type ][ $id ] ) ) {
       
  2136 								$nav_menu_item = array_merge( $core_content[ $type ][ $id ], $nav_menu_item );
       
  2137 							}
       
  2138 
       
  2139 							$content[ $type ][ $nav_menu_location ]['items'][] = $nav_menu_item;
       
  2140 						} elseif ( is_string( $nav_menu_item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $nav_menu_item ] ) ) {
       
  2141 							$content[ $type ][ $nav_menu_location ]['items'][] = $core_content[ $type ][ $nav_menu_item ];
       
  2142 						}
       
  2143 					}
       
  2144 				}
       
  2145 				break;
       
  2146 
       
  2147 			// Attachments are posts but have special treatment.
       
  2148 			case 'attachments' :
       
  2149 				foreach ( $config[ $type ] as $id => $item ) {
       
  2150 					if ( ! empty( $item['file'] ) ) {
       
  2151 						$content[ $type ][ $id ] = $item;
       
  2152 					}
       
  2153 				}
       
  2154 				break;
       
  2155 
       
  2156 			// All that's left now are posts (besides attachments). Not a default case for the sake of clarity and future work.
       
  2157 			case 'posts' :
       
  2158 				foreach ( $config[ $type ] as $id => $item ) {
       
  2159 					if ( is_array( $item ) ) {
       
  2160 
       
  2161 						// Item extends core content.
       
  2162 						if ( ! empty( $core_content[ $type ][ $id ] ) ) {
       
  2163 							$item = array_merge( $core_content[ $type ][ $id ], $item );
       
  2164 						}
       
  2165 
       
  2166 						// Enforce a subset of fields.
       
  2167 						$content[ $type ][ $id ] = wp_array_slice_assoc(
       
  2168 							$item,
       
  2169 							array(
       
  2170 								'post_type',
       
  2171 								'post_title',
       
  2172 								'post_excerpt',
       
  2173 								'post_name',
       
  2174 								'post_content',
       
  2175 								'menu_order',
       
  2176 								'comment_status',
       
  2177 								'thumbnail',
       
  2178 								'template',
       
  2179 							)
       
  2180 						);
       
  2181 					} elseif ( is_string( $item ) && ! empty( $core_content[ $type ][ $item ] ) ) {
       
  2182 						$content[ $type ][ $item ] = $core_content[ $type ][ $item ];
       
  2183 					}
       
  2184 				}
       
  2185 				break;
       
  2186 		}
       
  2187 	}
       
  2188 
       
  2189 	/**
       
  2190 	 * Filters the expanded array of starter content.
       
  2191 	 *
       
  2192 	 * @since 4.7.0
       
  2193 	 *
       
  2194 	 * @param array $content Array of starter content.
       
  2195 	 * @param array $config  Array of theme-specific starter content configuration.
       
  2196 	 */
       
  2197 	return apply_filters( 'get_theme_starter_content', $content, $config );
       
  2198 }
       
  2199 
       
  2200 /**
       
  2201  * Registers theme support for a given feature.
  1470  *
  2202  *
  1471  * Must be called in the theme's functions.php file to work.
  2203  * Must be called in the theme's functions.php file to work.
  1472  * If attached to a hook, it must be after_setup_theme.
  2204  * If attached to a hook, it must be {@see 'after_setup_theme'}.
  1473  * The init hook may be too late for some features.
  2205  * The {@see 'init'} hook may be too late for some features.
  1474  *
  2206  *
  1475  * @since 2.9.0
  2207  * @since 2.9.0
  1476  *
  2208  * @since 3.6.0 The `html5` feature was added
  1477  * @param string $feature The feature being added.
  2209  * @since 3.9.0 The `html5` feature now also accepts 'gallery' and 'caption'
       
  2210  * @since 4.1.0 The `title-tag` feature was added
       
  2211  * @since 4.5.0 The `customize-selective-refresh-widgets` feature was added
       
  2212  * @since 4.7.0 The `starter-content` feature was added
       
  2213  *
       
  2214  * @global array $_wp_theme_features
       
  2215  *
       
  2216  * @param string $feature  The feature being added. Likely core values include 'post-formats',
       
  2217  *                         'post-thumbnails', 'html5', 'custom-logo', 'custom-header-uploads',
       
  2218  *                         'custom-header', 'custom-background', 'title-tag', 'starter-content', etc.
       
  2219  * @param mixed  $args,... Optional extra arguments to pass along with certain features.
  1478  * @return void|bool False on failure, void otherwise.
  2220  * @return void|bool False on failure, void otherwise.
  1479  */
  2221  */
  1480 function add_theme_support( $feature ) {
  2222 function add_theme_support( $feature ) {
  1481 	global $_wp_theme_features;
  2223 	global $_wp_theme_features;
  1482 
  2224 
  1484 		$args = true;
  2226 		$args = true;
  1485 	else
  2227 	else
  1486 		$args = array_slice( func_get_args(), 1 );
  2228 		$args = array_slice( func_get_args(), 1 );
  1487 
  2229 
  1488 	switch ( $feature ) {
  2230 	switch ( $feature ) {
       
  2231 		case 'post-thumbnails':
       
  2232 			// All post types are already supported.
       
  2233 			if ( true === get_theme_support( 'post-thumbnails' ) ) {
       
  2234 				return;
       
  2235 			}
       
  2236 
       
  2237 			/*
       
  2238 			 * Merge post types with any that already declared their support
       
  2239 			 * for post thumbnails.
       
  2240 			 */
       
  2241 			if ( is_array( $args[0] ) && isset( $_wp_theme_features['post-thumbnails'] ) ) {
       
  2242 				$args[0] = array_unique( array_merge( $_wp_theme_features['post-thumbnails'][0], $args[0] ) );
       
  2243 			}
       
  2244 
       
  2245 			break;
       
  2246 
  1489 		case 'post-formats' :
  2247 		case 'post-formats' :
  1490 			if ( is_array( $args[0] ) ) {
  2248 			if ( is_array( $args[0] ) ) {
  1491 				$post_formats = get_post_format_slugs();
  2249 				$post_formats = get_post_format_slugs();
  1492 				unset( $post_formats['standard'] );
  2250 				unset( $post_formats['standard'] );
  1493 
  2251 
  1506 			}
  2264 			}
  1507 
  2265 
  1508 			// Calling 'html5' again merges, rather than overwrites.
  2266 			// Calling 'html5' again merges, rather than overwrites.
  1509 			if ( isset( $_wp_theme_features['html5'] ) )
  2267 			if ( isset( $_wp_theme_features['html5'] ) )
  1510 				$args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] );
  2268 				$args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] );
       
  2269 			break;
       
  2270 
       
  2271 		case 'custom-logo':
       
  2272 			if ( ! is_array( $args ) ) {
       
  2273 				$args = array( 0 => array() );
       
  2274 			}
       
  2275 			$defaults = array(
       
  2276 				'width'       => null,
       
  2277 				'height'      => null,
       
  2278 				'flex-width'  => false,
       
  2279 				'flex-height' => false,
       
  2280 				'header-text' => '',
       
  2281 			);
       
  2282 			$args[0] = wp_parse_args( array_intersect_key( $args[0], $defaults ), $defaults );
       
  2283 
       
  2284 			// Allow full flexibility if no size is specified.
       
  2285 			if ( is_null( $args[0]['width'] ) && is_null( $args[0]['height'] ) ) {
       
  2286 				$args[0]['flex-width']  = true;
       
  2287 				$args[0]['flex-height'] = true;
       
  2288 			}
  1511 			break;
  2289 			break;
  1512 
  2290 
  1513 		case 'custom-header-uploads' :
  2291 		case 'custom-header-uploads' :
  1514 			return add_theme_support( 'custom-header', array( 'uploads' => true ) );
  2292 			return add_theme_support( 'custom-header', array( 'uploads' => true ) );
  1515 
  2293 
  1528 				'header-text' => true,
  2306 				'header-text' => true,
  1529 				'uploads' => true,
  2307 				'uploads' => true,
  1530 				'wp-head-callback' => '',
  2308 				'wp-head-callback' => '',
  1531 				'admin-head-callback' => '',
  2309 				'admin-head-callback' => '',
  1532 				'admin-preview-callback' => '',
  2310 				'admin-preview-callback' => '',
       
  2311 				'video' => false,
       
  2312 				'video-active-callback' => 'is_front_page',
  1533 			);
  2313 			);
  1534 
  2314 
  1535 			$jit = isset( $args[0]['__jit'] );
  2315 			$jit = isset( $args[0]['__jit'] );
  1536 			unset( $args[0]['__jit'] );
  2316 			unset( $args[0]['__jit'] );
  1537 
  2317 
  1547 
  2327 
  1548 			// If a constant was defined, use that value. Otherwise, define the constant to ensure
  2328 			// If a constant was defined, use that value. Otherwise, define the constant to ensure
  1549 			// the constant is always accurate (and is not defined later,  overriding our value).
  2329 			// the constant is always accurate (and is not defined later,  overriding our value).
  1550 			// As stated above, the first value wins.
  2330 			// As stated above, the first value wins.
  1551 			// Once we get to wp_loaded (just-in-time), define any constants we haven't already.
  2331 			// Once we get to wp_loaded (just-in-time), define any constants we haven't already.
  1552 			// Constants are lame. Don't reference them. This is just for backwards compatibility.
  2332 			// Constants are lame. Don't reference them. This is just for backward compatibility.
  1553 
  2333 
  1554 			if ( defined( 'NO_HEADER_TEXT' ) )
  2334 			if ( defined( 'NO_HEADER_TEXT' ) )
  1555 				$args[0]['header-text'] = ! NO_HEADER_TEXT;
  2335 				$args[0]['header-text'] = ! NO_HEADER_TEXT;
  1556 			elseif ( isset( $args[0]['header-text'] ) )
  2336 			elseif ( isset( $args[0]['header-text'] ) )
  1557 				define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
  2337 				define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
  1594 			if ( ! is_array( $args ) )
  2374 			if ( ! is_array( $args ) )
  1595 				$args = array( 0 => array() );
  2375 				$args = array( 0 => array() );
  1596 
  2376 
  1597 			$defaults = array(
  2377 			$defaults = array(
  1598 				'default-image'          => '',
  2378 				'default-image'          => '',
       
  2379 				'default-preset'         => 'default',
       
  2380 				'default-position-x'     => 'left',
       
  2381 				'default-position-y'     => 'top',
       
  2382 				'default-size'           => 'auto',
  1599 				'default-repeat'         => 'repeat',
  2383 				'default-repeat'         => 'repeat',
  1600 				'default-position-x'     => 'left',
       
  1601 				'default-attachment'     => 'scroll',
  2384 				'default-attachment'     => 'scroll',
  1602 				'default-color'          => '',
  2385 				'default-color'          => '',
  1603 				'wp-head-callback'       => '_custom_background_cb',
  2386 				'wp-head-callback'       => '_custom_background_cb',
  1604 				'admin-head-callback'    => '',
  2387 				'admin-head-callback'    => '',
  1605 				'admin-preview-callback' => '',
  2388 				'admin-preview-callback' => '',
  1631 		case 'title-tag' :
  2414 		case 'title-tag' :
  1632 			// Can be called in functions.php but must happen before wp_loaded, i.e. not in header.php.
  2415 			// Can be called in functions.php but must happen before wp_loaded, i.e. not in header.php.
  1633 			if ( did_action( 'wp_loaded' ) ) {
  2416 			if ( did_action( 'wp_loaded' ) ) {
  1634 				/* translators: 1: Theme support 2: hook name */
  2417 				/* 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.' ),
  2418 				_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' );
  2419 					'<code>title-tag</code>', '<code>wp_loaded</code>' ), '4.1.0' );
  1637 
  2420 
  1638 				return false;
  2421 				return false;
  1639 			}
  2422 			}
  1640 	}
  2423 	}
  1641 
  2424 
  1645 /**
  2428 /**
  1646  * Registers the internal custom header and background routines.
  2429  * Registers the internal custom header and background routines.
  1647  *
  2430  *
  1648  * @since 3.4.0
  2431  * @since 3.4.0
  1649  * @access private
  2432  * @access private
       
  2433  *
       
  2434  * @global Custom_Image_Header $custom_image_header
       
  2435  * @global Custom_Background   $custom_background
  1650  */
  2436  */
  1651 function _custom_header_background_just_in_time() {
  2437 function _custom_header_background_just_in_time() {
  1652 	global $custom_image_header, $custom_background;
  2438 	global $custom_image_header, $custom_background;
  1653 
  2439 
  1654 	if ( current_theme_supports( 'custom-header' ) ) {
  2440 	if ( current_theme_supports( 'custom-header' ) ) {
  1678 		}
  2464 		}
  1679 	}
  2465 	}
  1680 }
  2466 }
  1681 
  2467 
  1682 /**
  2468 /**
       
  2469  * Adds CSS to hide header text for custom logo, based on Customizer setting.
       
  2470  *
       
  2471  * @since 4.5.0
       
  2472  * @access private
       
  2473  */
       
  2474 function _custom_logo_header_styles() {
       
  2475 	if ( ! current_theme_supports( 'custom-header', 'header-text' ) && get_theme_support( 'custom-logo', 'header-text' ) && ! get_theme_mod( 'header_text', true ) ) {
       
  2476 		$classes = (array) get_theme_support( 'custom-logo', 'header-text' );
       
  2477 		$classes = array_map( 'sanitize_html_class', $classes );
       
  2478 		$classes = '.' . implode( ', .', $classes );
       
  2479 
       
  2480 		?>
       
  2481 		<!-- Custom Logo: hide header text -->
       
  2482 		<style id="custom-logo-css" type="text/css">
       
  2483 			<?php echo $classes; ?> {
       
  2484 				position: absolute;
       
  2485 				clip: rect(1px, 1px, 1px, 1px);
       
  2486 			}
       
  2487 		</style>
       
  2488 	<?php
       
  2489 	}
       
  2490 }
       
  2491 
       
  2492 /**
  1683  * Gets the theme support arguments passed when registering that support
  2493  * Gets the theme support arguments passed when registering that support
  1684  *
  2494  *
  1685  * @since 3.1.0
  2495  * @since 3.1.0
       
  2496  *
       
  2497  * @global array $_wp_theme_features
  1686  *
  2498  *
  1687  * @param string $feature the feature to check
  2499  * @param string $feature the feature to check
  1688  * @return mixed The array of extra arguments or the value for the registered feature.
  2500  * @return mixed The array of extra arguments or the value for the registered feature.
  1689  */
  2501  */
  1690 function get_theme_support( $feature ) {
  2502 function get_theme_support( $feature ) {
  1695 	if ( func_num_args() <= 1 )
  2507 	if ( func_num_args() <= 1 )
  1696 		return $_wp_theme_features[ $feature ];
  2508 		return $_wp_theme_features[ $feature ];
  1697 
  2509 
  1698 	$args = array_slice( func_get_args(), 1 );
  2510 	$args = array_slice( func_get_args(), 1 );
  1699 	switch ( $feature ) {
  2511 	switch ( $feature ) {
       
  2512 		case 'custom-logo' :
  1700 		case 'custom-header' :
  2513 		case 'custom-header' :
  1701 		case 'custom-background' :
  2514 		case 'custom-background' :
  1702 			if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) )
  2515 			if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) )
  1703 				return $_wp_theme_features[ $feature ][0][ $args[0] ];
  2516 				return $_wp_theme_features[ $feature ][0][ $args[0] ];
  1704 			return false;
  2517 			return false;
  1715  * be used for child themes to override support from the parent theme.
  2528  * be used for child themes to override support from the parent theme.
  1716  *
  2529  *
  1717  * @since 3.0.0
  2530  * @since 3.0.0
  1718  * @see add_theme_support()
  2531  * @see add_theme_support()
  1719  * @param string $feature the feature being added
  2532  * @param string $feature the feature being added
  1720  * @return null|bool Whether feature was removed.
  2533  * @return bool|void Whether feature was removed.
  1721  */
  2534  */
  1722 function remove_theme_support( $feature ) {
  2535 function remove_theme_support( $feature ) {
  1723 	// Blacklist: for internal registrations not used directly by themes.
  2536 	// Blacklist: for internal registrations not used directly by themes.
  1724 	if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) )
  2537 	if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) )
  1725 		return false;
  2538 		return false;
  1730 /**
  2543 /**
  1731  * Do not use. Removes theme support internally, ignorant of the blacklist.
  2544  * Do not use. Removes theme support internally, ignorant of the blacklist.
  1732  *
  2545  *
  1733  * @access private
  2546  * @access private
  1734  * @since 3.1.0
  2547  * @since 3.1.0
       
  2548  *
       
  2549  * @global array               $_wp_theme_features
       
  2550  * @global Custom_Image_Header $custom_image_header
       
  2551  * @global Custom_Background   $custom_background
       
  2552  *
  1735  * @param string $feature
  2553  * @param string $feature
  1736  */
  2554  */
  1737 function _remove_theme_support( $feature ) {
  2555 function _remove_theme_support( $feature ) {
  1738 	global $_wp_theme_features;
  2556 	global $_wp_theme_features;
  1739 
  2557 
  1751 	switch ( $feature ) {
  2569 	switch ( $feature ) {
  1752 		case 'custom-header' :
  2570 		case 'custom-header' :
  1753 			if ( ! did_action( 'wp_loaded' ) )
  2571 			if ( ! did_action( 'wp_loaded' ) )
  1754 				break;
  2572 				break;
  1755 			$support = get_theme_support( 'custom-header' );
  2573 			$support = get_theme_support( 'custom-header' );
  1756 			if ( $support[0]['wp-head-callback'] )
  2574 			if ( isset( $support[0]['wp-head-callback'] ) ) {
  1757 				remove_action( 'wp_head', $support[0]['wp-head-callback'] );
  2575 				remove_action( 'wp_head', $support[0]['wp-head-callback'] );
  1758 			remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) );
  2576 			}
  1759 			unset( $GLOBALS['custom_image_header'] );
  2577 			if ( isset( $GLOBALS['custom_image_header'] ) ) {
       
  2578 				remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) );
       
  2579 				unset( $GLOBALS['custom_image_header'] );
       
  2580 			}
  1760 			break;
  2581 			break;
  1761 
  2582 
  1762 		case 'custom-background' :
  2583 		case 'custom-background' :
  1763 			if ( ! did_action( 'wp_loaded' ) )
  2584 			if ( ! did_action( 'wp_loaded' ) )
  1764 				break;
  2585 				break;
  1775 
  2596 
  1776 /**
  2597 /**
  1777  * Checks a theme's support for a given feature
  2598  * Checks a theme's support for a given feature
  1778  *
  2599  *
  1779  * @since 2.9.0
  2600  * @since 2.9.0
       
  2601  *
       
  2602  * @global array $_wp_theme_features
       
  2603  *
  1780  * @param string $feature the feature being checked
  2604  * @param string $feature the feature being checked
  1781  * @return boolean
  2605  * @return bool
  1782  */
  2606  */
  1783 function current_theme_supports( $feature ) {
  2607 function current_theme_supports( $feature ) {
  1784 	global $_wp_theme_features;
  2608 	global $_wp_theme_features;
  1785 
  2609 
  1786 	if ( 'custom-header-uploads' == $feature )
  2610 	if ( 'custom-header-uploads' == $feature )
  1787 		return current_theme_supports( 'custom-header', 'uploads' );
  2611 		return current_theme_supports( 'custom-header', 'uploads' );
  1788 
  2612 
  1789 	if ( !isset( $_wp_theme_features[$feature] ) )
  2613 	if ( !isset( $_wp_theme_features[$feature] ) )
  1790 		return false;
  2614 		return false;
  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 
  2615 
  1800 	// If no args passed then no extra checks need be performed
  2616 	// If no args passed then no extra checks need be performed
  1801 	if ( func_num_args() <= 1 )
  2617 	if ( func_num_args() <= 1 )
  1802 		return true;
  2618 		return true;
  1803 
  2619 
  1821 			// Specific areas of HTML5 support *must* be passed via an array to add_theme_support()
  2637 			// Specific areas of HTML5 support *must* be passed via an array to add_theme_support()
  1822 
  2638 
  1823 			$type = $args[0];
  2639 			$type = $args[0];
  1824 			return in_array( $type, $_wp_theme_features[$feature][0] );
  2640 			return in_array( $type, $_wp_theme_features[$feature][0] );
  1825 
  2641 
       
  2642 		case 'custom-logo':
  1826 		case 'custom-header':
  2643 		case 'custom-header':
  1827 		case 'custom-background' :
  2644 		case 'custom-background':
  1828 			// specific custom header and background capabilities can be registered by passing
  2645 			// Specific capabilities can be registered by passing an array to add_theme_support().
  1829 			// an array to add_theme_support()
  2646 			return ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) && $_wp_theme_features[ $feature ][0][ $args[0] ] );
  1830 			$header_support = $args[0];
       
  1831 			return ( isset( $_wp_theme_features[$feature][0][$header_support] ) && $_wp_theme_features[$feature][0][$header_support] );
       
  1832 	}
  2647 	}
  1833 
  2648 
  1834 	/**
  2649 	/**
  1835 	 * Filter whether the current theme supports a specific feature.
  2650 	 * Filters whether the current theme supports a specific feature.
  1836 	 *
  2651 	 *
  1837 	 * The dynamic portion of the hook name, `$feature`, refers to the specific theme
  2652 	 * The dynamic portion of the hook name, `$feature`, refers to the specific theme
  1838 	 * feature. Possible values include 'post-formats', 'post-thumbnails', 'custom-background',
  2653 	 * feature. Possible values include 'post-formats', 'post-thumbnails', 'custom-background',
  1839 	 * 'custom-header', 'menus', 'automatic-feed-links', and 'html5'.
  2654 	 * 'custom-header', 'menus', 'automatic-feed-links', 'html5',
       
  2655 	 * 'starter-content', and 'customize-selective-refresh-widgets'.
  1840 	 *
  2656 	 *
  1841 	 * @since 3.4.0
  2657 	 * @since 3.4.0
  1842 	 *
  2658 	 *
  1843 	 * @param bool   true     Whether the current theme supports the given feature. Default true.
  2659 	 * @param bool   true     Whether the current theme supports the given feature. Default true.
  1844 	 * @param array  $args    Array of arguments for the feature.
  2660 	 * @param array  $args    Array of arguments for the feature.
  1866 
  2682 
  1867 /**
  2683 /**
  1868  * Checks an attachment being deleted to see if it's a header or background image.
  2684  * Checks an attachment being deleted to see if it's a header or background image.
  1869  *
  2685  *
  1870  * If true it removes the theme modification which would be pointing at the deleted
  2686  * If true it removes the theme modification which would be pointing at the deleted
  1871  * attachment
  2687  * attachment.
  1872  *
  2688  *
  1873  * @access private
  2689  * @access private
  1874  * @since 3.0.0
  2690  * @since 3.0.0
  1875  * @param int $id the attachment id
  2691  * @since 4.3.0 Also removes `header_image_data`.
       
  2692  * @since 4.5.0 Also removes custom logo theme mods.
       
  2693  *
       
  2694  * @param int $id The attachment id.
  1876  */
  2695  */
  1877 function _delete_attachment_theme_mod( $id ) {
  2696 function _delete_attachment_theme_mod( $id ) {
  1878 	$attachment_image = wp_get_attachment_url( $id );
  2697 	$attachment_image = wp_get_attachment_url( $id );
  1879 	$header_image = get_header_image();
  2698 	$header_image     = get_header_image();
  1880 	$background_image = get_background_image();
  2699 	$background_image = get_background_image();
  1881 
  2700 	$custom_logo_id   = get_theme_mod( 'custom_logo' );
  1882 	if ( $header_image && $header_image == $attachment_image )
  2701 
       
  2702 	if ( $custom_logo_id && $custom_logo_id == $id ) {
       
  2703 		remove_theme_mod( 'custom_logo' );
       
  2704 		remove_theme_mod( 'header_text' );
       
  2705 	}
       
  2706 
       
  2707 	if ( $header_image && $header_image == $attachment_image ) {
  1883 		remove_theme_mod( 'header_image' );
  2708 		remove_theme_mod( 'header_image' );
  1884 
  2709 		remove_theme_mod( 'header_image_data' );
  1885 	if ( $background_image && $background_image == $attachment_image )
  2710 	}
       
  2711 
       
  2712 	if ( $background_image && $background_image == $attachment_image ) {
  1886 		remove_theme_mod( 'background_image' );
  2713 		remove_theme_mod( 'background_image' );
  1887 }
  2714 	}
  1888 
  2715 }
  1889 /**
  2716 
  1890  * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load
  2717 /**
       
  2718  * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load.
       
  2719  *
       
  2720  * See {@see 'after_switch_theme'}.
  1891  *
  2721  *
  1892  * @since 3.3.0
  2722  * @since 3.3.0
  1893  */
  2723  */
  1894 function check_theme_switched() {
  2724 function check_theme_switched() {
  1895 	if ( $stylesheet = get_option( 'theme_switched' ) ) {
  2725 	if ( $stylesheet = get_option( 'theme_switched' ) ) {
  1896 		$old_theme = wp_get_theme( $stylesheet );
  2726 		$old_theme = wp_get_theme( $stylesheet );
  1897 
  2727 
  1898 		// Prevent retrieve_widgets() from running since Customizer already called it up front
  2728 		// Prevent widget & menu mapping from running since Customizer already called it up front
  1899 		if ( get_option( 'theme_switched_via_customizer' ) ) {
  2729 		if ( get_option( 'theme_switched_via_customizer' ) ) {
       
  2730 			remove_action( 'after_switch_theme', '_wp_menus_changed' );
  1900 			remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
  2731 			remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
  1901 			update_option( 'theme_switched_via_customizer', false );
  2732 			update_option( 'theme_switched_via_customizer', false );
  1902 		}
  2733 		}
  1903 
  2734 
  1904 		if ( $old_theme->exists() ) {
  2735 		if ( $old_theme->exists() ) {
  1916 			 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
  2747 			 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
  1917 			 */
  2748 			 */
  1918 			do_action( 'after_switch_theme', $old_theme->get( 'Name' ), $old_theme );
  2749 			do_action( 'after_switch_theme', $old_theme->get( 'Name' ), $old_theme );
  1919 		} else {
  2750 		} else {
  1920 			/** This action is documented in wp-includes/theme.php */
  2751 			/** This action is documented in wp-includes/theme.php */
  1921 			do_action( 'after_switch_theme', $stylesheet );
  2752 			do_action( 'after_switch_theme', $stylesheet, $old_theme );
  1922 		}
  2753 		}
       
  2754 		flush_rewrite_rules();
  1923 
  2755 
  1924 		update_option( 'theme_switched', false );
  2756 		update_option( 'theme_switched', false );
  1925 	}
  2757 	}
  1926 }
  2758 }
  1927 
  2759 
  1928 /**
  2760 /**
  1929  * Includes and instantiates the WP_Customize_Manager class.
  2761  * Includes and instantiates the WP_Customize_Manager class.
  1930  *
  2762  *
  1931  * Fires when ?wp_customize=on or on wp-admin/customize.php.
  2763  * Loads the Customizer at plugins_loaded when accessing the customize.php admin
       
  2764  * page or when any request includes a wp_customize=on param or a customize_changeset
       
  2765  * param (a UUID). This param is a signal for whether to bootstrap the Customizer when
       
  2766  * WordPress is loading, especially in the Customizer preview
       
  2767  * or when making Customizer Ajax requests for widgets or menus.
  1932  *
  2768  *
  1933  * @since 3.4.0
  2769  * @since 3.4.0
       
  2770  *
       
  2771  * @global WP_Customize_Manager $wp_customize
  1934  */
  2772  */
  1935 function _wp_customize_include() {
  2773 function _wp_customize_include() {
  1936 	if ( ! ( ( isset( $_REQUEST['wp_customize'] ) && 'on' == $_REQUEST['wp_customize'] )
  2774 
  1937 		|| ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) )
  2775 	$is_customize_admin_page = ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) );
  1938 	) )
  2776 	$should_include = (
       
  2777 		$is_customize_admin_page
       
  2778 		||
       
  2779 		( isset( $_REQUEST['wp_customize'] ) && 'on' == $_REQUEST['wp_customize'] )
       
  2780 		||
       
  2781 		( ! empty( $_GET['customize_changeset_uuid'] ) || ! empty( $_POST['customize_changeset_uuid'] ) )
       
  2782 	);
       
  2783 
       
  2784 	if ( ! $should_include ) {
  1939 		return;
  2785 		return;
  1940 
  2786 	}
  1941 	require( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
  2787 
  1942 	// Init Customize class
  2788 	/*
  1943 	$GLOBALS['wp_customize'] = new WP_Customize_Manager;
  2789 	 * Note that wp_unslash() is not being used on the input vars because it is
       
  2790 	 * called before wp_magic_quotes() gets called. Besides this fact, none of
       
  2791 	 * the values should contain any characters needing slashes anyway.
       
  2792 	 */
       
  2793 	$keys = array( 'changeset_uuid', 'customize_changeset_uuid', 'customize_theme', 'theme', 'customize_messenger_channel', 'customize_autosaved' );
       
  2794 	$input_vars = array_merge(
       
  2795 		wp_array_slice_assoc( $_GET, $keys ),
       
  2796 		wp_array_slice_assoc( $_POST, $keys )
       
  2797 	);
       
  2798 
       
  2799 	$theme = null;
       
  2800 	$changeset_uuid = false; // Value false indicates UUID should be determined after_setup_theme to either re-use existing saved changeset or else generate a new UUID if none exists.
       
  2801 	$messenger_channel = null;
       
  2802 	$autosaved = null;
       
  2803 	$branching = false; // Set initially fo false since defaults to true for back-compat; can be overridden via the customize_changeset_branching filter.
       
  2804 
       
  2805 	if ( $is_customize_admin_page && isset( $input_vars['changeset_uuid'] ) ) {
       
  2806 		$changeset_uuid = sanitize_key( $input_vars['changeset_uuid'] );
       
  2807 	} elseif ( ! empty( $input_vars['customize_changeset_uuid'] ) ) {
       
  2808 		$changeset_uuid = sanitize_key( $input_vars['customize_changeset_uuid'] );
       
  2809 	}
       
  2810 
       
  2811 	// Note that theme will be sanitized via WP_Theme.
       
  2812 	if ( $is_customize_admin_page && isset( $input_vars['theme'] ) ) {
       
  2813 		$theme = $input_vars['theme'];
       
  2814 	} elseif ( isset( $input_vars['customize_theme'] ) ) {
       
  2815 		$theme = $input_vars['customize_theme'];
       
  2816 	}
       
  2817 
       
  2818 	if ( ! empty( $input_vars['customize_autosaved'] ) ) {
       
  2819 		$autosaved = true;
       
  2820 	}
       
  2821 
       
  2822 	if ( isset( $input_vars['customize_messenger_channel'] ) ) {
       
  2823 		$messenger_channel = sanitize_key( $input_vars['customize_messenger_channel'] );
       
  2824 	}
       
  2825 
       
  2826 	/*
       
  2827 	 * Note that settings must be previewed even outside the customizer preview
       
  2828 	 * and also in the customizer pane itself. This is to enable loading an existing
       
  2829 	 * changeset into the customizer. Previewing the settings only has to be prevented
       
  2830 	 * here in the case of a customize_save action because this will cause WP to think
       
  2831 	 * there is nothing changed that needs to be saved.
       
  2832 	 */
       
  2833 	$is_customize_save_action = (
       
  2834 		wp_doing_ajax()
       
  2835 		&&
       
  2836 		isset( $_REQUEST['action'] )
       
  2837 		&&
       
  2838 		'customize_save' === wp_unslash( $_REQUEST['action'] )
       
  2839 	);
       
  2840 	$settings_previewed = ! $is_customize_save_action;
       
  2841 
       
  2842 	require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
       
  2843 	$GLOBALS['wp_customize'] = new WP_Customize_Manager( compact( 'changeset_uuid', 'theme', 'messenger_channel', 'settings_previewed', 'autosaved', 'branching' ) );
       
  2844 }
       
  2845 
       
  2846 /**
       
  2847  * Publishes a snapshot's changes.
       
  2848  *
       
  2849  * @since 4.7.0
       
  2850  * @access private
       
  2851  *
       
  2852  * @global wpdb                 $wpdb         WordPress database abstraction object.
       
  2853  * @global WP_Customize_Manager $wp_customize Customizer instance.
       
  2854  *
       
  2855  * @param string  $new_status     New post status.
       
  2856  * @param string  $old_status     Old post status.
       
  2857  * @param WP_Post $changeset_post Changeset post object.
       
  2858  */
       
  2859 function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_post ) {
       
  2860 	global $wp_customize, $wpdb;
       
  2861 
       
  2862 	$is_publishing_changeset = (
       
  2863 		'customize_changeset' === $changeset_post->post_type
       
  2864 		&&
       
  2865 		'publish' === $new_status
       
  2866 		&&
       
  2867 		'publish' !== $old_status
       
  2868 	);
       
  2869 	if ( ! $is_publishing_changeset ) {
       
  2870 		return;
       
  2871 	}
       
  2872 
       
  2873 	if ( empty( $wp_customize ) ) {
       
  2874 		require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
       
  2875 		$wp_customize = new WP_Customize_Manager( array(
       
  2876 			'changeset_uuid' => $changeset_post->post_name,
       
  2877 			'settings_previewed' => false,
       
  2878 		) );
       
  2879 	}
       
  2880 
       
  2881 	if ( ! did_action( 'customize_register' ) ) {
       
  2882 		/*
       
  2883 		 * When running from CLI or Cron, the customize_register action will need
       
  2884 		 * to be triggered in order for core, themes, and plugins to register their
       
  2885 		 * settings. Normally core will add_action( 'customize_register' ) at
       
  2886 		 * priority 10 to register the core settings, and if any themes/plugins
       
  2887 		 * also add_action( 'customize_register' ) at the same priority, they
       
  2888 		 * will have a $wp_customize with those settings registered since they
       
  2889 		 * call add_action() afterward, normally. However, when manually doing
       
  2890 		 * the customize_register action after the setup_theme, then the order
       
  2891 		 * will be reversed for two actions added at priority 10, resulting in
       
  2892 		 * the core settings no longer being available as expected to themes/plugins.
       
  2893 		 * So the following manually calls the method that registers the core
       
  2894 		 * settings up front before doing the action.
       
  2895 		 */
       
  2896 		remove_action( 'customize_register', array( $wp_customize, 'register_controls' ) );
       
  2897 		$wp_customize->register_controls();
       
  2898 
       
  2899 		/** This filter is documented in /wp-includes/class-wp-customize-manager.php */
       
  2900 		do_action( 'customize_register', $wp_customize );
       
  2901 	}
       
  2902 	$wp_customize->_publish_changeset_values( $changeset_post->ID ) ;
       
  2903 
       
  2904 	/*
       
  2905 	 * Trash the changeset post if revisions are not enabled. Unpublished
       
  2906 	 * changesets by default get garbage collected due to the auto-draft status.
       
  2907 	 * When a changeset post is published, however, it would no longer get cleaned
       
  2908 	 * out. Ths is a problem when the changeset posts are never displayed anywhere,
       
  2909 	 * since they would just be endlessly piling up. So here we use the revisions
       
  2910 	 * feature to indicate whether or not a published changeset should get trashed
       
  2911 	 * and thus garbage collected.
       
  2912 	 */
       
  2913 	if ( ! wp_revisions_enabled( $changeset_post ) ) {
       
  2914 		$wp_customize->trash_changeset_post( $changeset_post->ID );
       
  2915 	}
       
  2916 }
       
  2917 
       
  2918 /**
       
  2919  * Filters changeset post data upon insert to ensure post_name is intact.
       
  2920  *
       
  2921  * This is needed to prevent the post_name from being dropped when the post is
       
  2922  * transitioned into pending status by a contributor.
       
  2923  *
       
  2924  * @since 4.7.0
       
  2925  * @see wp_insert_post()
       
  2926  *
       
  2927  * @param array $post_data          An array of slashed post data.
       
  2928  * @param array $supplied_post_data An array of sanitized, but otherwise unmodified post data.
       
  2929  * @returns array Filtered data.
       
  2930  */
       
  2931 function _wp_customize_changeset_filter_insert_post_data( $post_data, $supplied_post_data ) {
       
  2932 	if ( isset( $post_data['post_type'] ) && 'customize_changeset' === $post_data['post_type'] ) {
       
  2933 
       
  2934 		// Prevent post_name from being dropped, such as when contributor saves a changeset post as pending.
       
  2935 		if ( empty( $post_data['post_name'] ) && ! empty( $supplied_post_data['post_name'] ) ) {
       
  2936 			$post_data['post_name'] = $supplied_post_data['post_name'];
       
  2937 		}
       
  2938 	}
       
  2939 	return $post_data;
  1944 }
  2940 }
  1945 
  2941 
  1946 /**
  2942 /**
  1947  * Adds settings for the customize-loader script.
  2943  * Adds settings for the customize-loader script.
  1948  *
  2944  *
  1949  * @since 3.4.0
  2945  * @since 3.4.0
  1950  */
  2946  */
  1951 function _wp_customize_loader_settings() {
  2947 function _wp_customize_loader_settings() {
  1952 	global $wp_scripts;
       
  1953 
       
  1954 	$admin_origin = parse_url( admin_url() );
  2948 	$admin_origin = parse_url( admin_url() );
  1955 	$home_origin  = parse_url( home_url() );
  2949 	$home_origin  = parse_url( home_url() );
  1956 	$cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) );
  2950 	$cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) );
  1957 
  2951 
  1958 	$browser = array(
  2952 	$browser = array(
  1970 		),
  2964 		),
  1971 	);
  2965 	);
  1972 
  2966 
  1973 	$script = 'var _wpCustomizeLoaderSettings = ' . wp_json_encode( $settings ) . ';';
  2967 	$script = 'var _wpCustomizeLoaderSettings = ' . wp_json_encode( $settings ) . ';';
  1974 
  2968 
       
  2969 	$wp_scripts = wp_scripts();
  1975 	$data = $wp_scripts->get_data( 'customize-loader', 'data' );
  2970 	$data = $wp_scripts->get_data( 'customize-loader', 'data' );
  1976 	if ( $data )
  2971 	if ( $data )
  1977 		$script = "$data\n$script";
  2972 		$script = "$data\n$script";
  1978 
  2973 
  1979 	$wp_scripts->add_data( 'customize-loader', 'data', $script );
  2974 	$wp_scripts->add_data( 'customize-loader', 'data', $script );
  1983  * Returns a URL to load the Customizer.
  2978  * Returns a URL to load the Customizer.
  1984  *
  2979  *
  1985  * @since 3.4.0
  2980  * @since 3.4.0
  1986  *
  2981  *
  1987  * @param string $stylesheet Optional. Theme to customize. Defaults to current theme.
  2982  * @param string $stylesheet Optional. Theme to customize. Defaults to current theme.
  1988  * 	The theme's stylesheet will be urlencoded if necessary.
  2983  * 	                         The theme's stylesheet will be urlencoded if necessary.
       
  2984  * @return string
  1989  */
  2985  */
  1990 function wp_customize_url( $stylesheet = null ) {
  2986 function wp_customize_url( $stylesheet = null ) {
  1991 	$url = admin_url( 'customize.php' );
  2987 	$url = admin_url( 'customize.php' );
  1992 	if ( $stylesheet )
  2988 	if ( $stylesheet )
  1993 		$url .= '?theme=' . urlencode( $stylesheet );
  2989 		$url .= '?theme=' . urlencode( $stylesheet );
  2006  *
  3002  *
  2007  * It is also recommended that you add the "no-customize-support" class
  3003  * It is also recommended that you add the "no-customize-support" class
  2008  * to the body tag by default.
  3004  * to the body tag by default.
  2009  *
  3005  *
  2010  * @since 3.4.0
  3006  * @since 3.4.0
       
  3007  * @since 4.7.0 Support for IE8 and below is explicitly removed via conditional comments.
  2011  */
  3008  */
  2012 function wp_customize_support_script() {
  3009 function wp_customize_support_script() {
  2013 	$admin_origin = parse_url( admin_url() );
  3010 	$admin_origin = parse_url( admin_url() );
  2014 	$home_origin  = parse_url( home_url() );
  3011 	$home_origin  = parse_url( home_url() );
  2015 	$cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) );
  3012 	$cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) );
  2016 
  3013 
  2017 	?>
  3014 	?>
  2018 	<script type="text/javascript">
  3015 	<!--[if lte IE 8]>
  2019 		(function() {
  3016 		<script type="text/javascript">
  2020 			var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)');
  3017 			document.body.className = document.body.className.replace( /(^|\s)(no-)?customize-support(?=\s|$)/, '' ) + ' no-customize-support';
  2021 
  3018 		</script>
  2022 <?php		if ( $cross_domain ): ?>
  3019 	<![endif]-->
  2023 			request = (function(){ var xhr = new XMLHttpRequest(); return ('withCredentials' in xhr); })();
  3020 	<!--[if gte IE 9]><!-->
  2024 <?php		else: ?>
  3021 		<script type="text/javascript">
  2025 			request = true;
  3022 			(function() {
  2026 <?php		endif; ?>
  3023 				var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)');
  2027 
  3024 
  2028 			b[c] = b[c].replace( rcs, ' ' );
  3025 		<?php	if ( $cross_domain ) : ?>
  2029 			b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
  3026 				request = (function(){ var xhr = new XMLHttpRequest(); return ('withCredentials' in xhr); })();
  2030 		}());
  3027 		<?php	else : ?>
  2031 	</script>
  3028 				request = true;
       
  3029 		<?php	endif; ?>
       
  3030 
       
  3031 				b[c] = b[c].replace( rcs, ' ' );
       
  3032 				// The customizer requires postMessage and CORS (if the site is cross domain)
       
  3033 				b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
       
  3034 			}());
       
  3035 		</script>
       
  3036 	<!--<![endif]-->
  2032 	<?php
  3037 	<?php
  2033 }
  3038 }
  2034 
  3039 
  2035 /**
  3040 /**
  2036  * Whether the site is being previewed in the Customizer.
  3041  * Whether the site is being previewed in the Customizer.
  2044 function is_customize_preview() {
  3049 function is_customize_preview() {
  2045 	global $wp_customize;
  3050 	global $wp_customize;
  2046 
  3051 
  2047 	return ( $wp_customize instanceof WP_Customize_Manager ) && $wp_customize->is_preview();
  3052 	return ( $wp_customize instanceof WP_Customize_Manager ) && $wp_customize->is_preview();
  2048 }
  3053 }
       
  3054 
       
  3055 /**
       
  3056  * Make sure that auto-draft posts get their post_date bumped or status changed to draft to prevent premature garbage-collection.
       
  3057  *
       
  3058  * When a changeset is updated but remains an auto-draft, ensure the post_date
       
  3059  * for the auto-draft posts remains the same so that it will be
       
  3060  * garbage-collected at the same time by `wp_delete_auto_drafts()`. Otherwise,
       
  3061  * if the changeset is updated to be a draft then update the posts
       
  3062  * to have a far-future post_date so that they will never be garbage collected
       
  3063  * unless the changeset post itself is deleted.
       
  3064  *
       
  3065  * When a changeset is updated to be a persistent draft or to be scheduled for
       
  3066  * publishing, then transition any dependent auto-drafts to a draft status so
       
  3067  * that they likewise will not be garbage-collected but also so that they can
       
  3068  * be edited in the admin before publishing since there is not yet a post/page
       
  3069  * editing flow in the Customizer. See #39752.
       
  3070  *
       
  3071  * @link https://core.trac.wordpress.org/ticket/39752
       
  3072  *
       
  3073  * @since 4.8.0
       
  3074  * @access private
       
  3075  * @see wp_delete_auto_drafts()
       
  3076  *
       
  3077  * @param string   $new_status Transition to this post status.
       
  3078  * @param string   $old_status Previous post status.
       
  3079  * @param \WP_Post $post       Post data.
       
  3080  * @global wpdb $wpdb
       
  3081  */
       
  3082 function _wp_keep_alive_customize_changeset_dependent_auto_drafts( $new_status, $old_status, $post ) {
       
  3083 	global $wpdb;
       
  3084 	unset( $old_status );
       
  3085 
       
  3086 	// Short-circuit if not a changeset or if the changeset was published.
       
  3087 	if ( 'customize_changeset' !== $post->post_type || 'publish' === $new_status ) {
       
  3088 		return;
       
  3089 	}
       
  3090 
       
  3091 	$data = json_decode( $post->post_content, true );
       
  3092 	if ( empty( $data['nav_menus_created_posts']['value'] ) ) {
       
  3093 		return;
       
  3094 	}
       
  3095 
       
  3096 	/*
       
  3097 	 * Actually, in lieu of keeping alive, trash any customization drafts here if the changeset itself is
       
  3098 	 * getting trashed. This is needed because when a changeset transitions to a draft, then any of the
       
  3099 	 * dependent auto-draft post/page stubs will also get transitioned to customization drafts which
       
  3100 	 * are then visible in the WP Admin. We cannot wait for the deletion of the changeset in which
       
  3101 	 * _wp_delete_customize_changeset_dependent_auto_drafts() will be called, since they need to be
       
  3102 	 * trashed to remove from visibility immediately.
       
  3103 	 */
       
  3104 	if ( 'trash' === $new_status ) {
       
  3105 		foreach ( $data['nav_menus_created_posts']['value'] as $post_id ) {
       
  3106 			if ( ! empty( $post_id ) && 'draft' === get_post_status( $post_id ) ) {
       
  3107 				wp_trash_post( $post_id );
       
  3108 			}
       
  3109 		}
       
  3110 		return;
       
  3111 	}
       
  3112 
       
  3113 	$post_args = array();
       
  3114 	if ( 'auto-draft' === $new_status ) {
       
  3115 		/*
       
  3116 		 * Keep the post date for the post matching the changeset
       
  3117 		 * so that it will not be garbage-collected before the changeset.
       
  3118 		 */
       
  3119 		$post_args['post_date'] = $post->post_date; // Note wp_delete_auto_drafts() only looks at this date.
       
  3120 	} else {
       
  3121 		/*
       
  3122 		 * Since the changeset no longer has an auto-draft (and it is not published)
       
  3123 		 * it is now a persistent changeset, a long-lived draft, and so any
       
  3124 		 * associated auto-draft posts should likewise transition into having a draft
       
  3125 		 * status. These drafts will be treated differently than regular drafts in
       
  3126 		 * that they will be tied to the given changeset. The publish metabox is
       
  3127 		 * replaced with a notice about how the post is part of a set of customized changes
       
  3128 		 * which will be published when the changeset is published.
       
  3129 		 */
       
  3130 		$post_args['post_status'] = 'draft';
       
  3131 	}
       
  3132 
       
  3133 	foreach ( $data['nav_menus_created_posts']['value'] as $post_id ) {
       
  3134 		if ( empty( $post_id ) || 'auto-draft' !== get_post_status( $post_id ) ) {
       
  3135 			continue;
       
  3136 		}
       
  3137 		$wpdb->update(
       
  3138 			$wpdb->posts,
       
  3139 			$post_args,
       
  3140 			array( 'ID' => $post_id )
       
  3141 		);
       
  3142 		clean_post_cache( $post_id );
       
  3143 	}
       
  3144 }