'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'lazy_load_term_meta' => false,
if ( get_stylesheet() === $stylesheet ) {
$post_id = get_theme_mod( 'custom_css_post_id' );
if ( $post_id > 0 && get_post( $post_id ) ) {
$post = get_post( $post_id );
// `-1` indicates no post exists; no query necessary.
if ( ! $post && -1 !== $post_id ) {
$query = new WP_Query( $custom_css_query_vars );
* Cache the lookup. See wp_update_custom_css_post().
* @todo This should get cleared if a custom_css post is added/removed.
set_theme_mod( 'custom_css_post_id', $post ? $post->ID : -1 );
$query = new WP_Query( $custom_css_query_vars );
* Fetches the saved Custom CSS content for rendering.
* @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the active theme.
* @return string The Custom CSS Post content.
function wp_get_custom_css( $stylesheet = '' ) {
if ( empty( $stylesheet ) ) {
$stylesheet = get_stylesheet();
$post = wp_get_custom_css_post( $stylesheet );
$css = $post->post_content;
* Filters the custom CSS output into the head element.
* @param string $css CSS pulled in from the Custom CSS post type.
* @param string $stylesheet The theme stylesheet name.
$css = apply_filters( 'wp_get_custom_css', $css, $stylesheet );
* Updates the `custom_css` post for a given theme.
* Inserts a `custom_css` post when one doesn't yet exist.
* @param string $css CSS, stored in `post_content`.
* @type string $preprocessed Optional. Pre-processed CSS, stored in `post_content_filtered`.
* @type string $stylesheet Optional. Stylesheet (child theme) to update.
* Defaults to active theme/stylesheet.
* @return WP_Post|WP_Error Post on success, error on failure.
function wp_update_custom_css_post( $css, $args = array() ) {
'stylesheet' => get_stylesheet(),
'preprocessed' => $args['preprocessed'],
* Filters the `css` (`post_content`) and `preprocessed` (`post_content_filtered`) args
* for a `custom_css` post being updated.
* This filter can be used by plugin that offer CSS pre-processors, to store the original
* pre-processed CSS in `post_content_filtered` and then store processed CSS in `post_content`.
* When used in this way, the `post_content_filtered` should be supplied as the setting value
* instead of `post_content` via a the `customize_value_custom_css` filter, for example:
* add_filter( 'customize_value_custom_css', function( $value, $setting ) {
* $post = wp_get_custom_css_post( $setting->stylesheet );
* if ( $post && ! empty( $post->post_content_filtered ) ) {
* $css = $post->post_content_filtered;
* @type string $css CSS stored in `post_content`.
* @type string $preprocessed Pre-processed CSS stored in `post_content_filtered`.
* The args passed into `wp_update_custom_css_post()` merged with defaults.
* @type string $css The original CSS passed in to be updated.
* @type string $preprocessed The original preprocessed CSS passed in to be updated.
* @type string $stylesheet The stylesheet (theme) being updated.
$data = apply_filters( 'update_custom_css_data', $data, array_merge( $args, compact( 'css' ) ) );
'post_title' => $args['stylesheet'],
'post_name' => sanitize_title( $args['stylesheet'] ),
'post_type' => 'custom_css',
'post_status' => 'publish',
'post_content' => $data['css'],
'post_content_filtered' => $data['preprocessed'],
// Update post if it already exists, otherwise create a new one.
$post = wp_get_custom_css_post( $args['stylesheet'] );
$post_data['ID'] = $post->ID;
$r = wp_update_post( wp_slash( $post_data ), true );
$r = wp_insert_post( wp_slash( $post_data ), true );
if ( ! is_wp_error( $r ) ) {
if ( get_stylesheet() === $args['stylesheet'] ) {
set_theme_mod( 'custom_css_post_id', $r );
// Trigger creation of a revision. This should be removed once #30854 is resolved.
$revisions = wp_get_latest_revision_id_and_total_count( $r );
if ( ! is_wp_error( $revisions ) && 0 === $revisions['count'] ) {
wp_save_post_revision( $r );
if ( is_wp_error( $r ) ) {
* Adds callback for custom TinyMCE editor stylesheets.
* The parameter $stylesheet is the name of the stylesheet, relative to
* the theme root. It also accepts an array of stylesheets.
* It is optional and defaults to 'editor-style.css'.
* This function automatically adds another stylesheet with -rtl prefix, e.g. editor-style-rtl.css.
* If that file doesn't exist, it is removed before adding the stylesheet(s) to TinyMCE.
* If an array of stylesheets is passed to add_editor_style(),
* RTL is only added for the first stylesheet.
* Since version 3.4 the TinyMCE body has .rtl CSS class.
* It is a better option to use that class and add any RTL styles to the main stylesheet.
* @global array $editor_styles
* @param array|string $stylesheet Optional. Stylesheet name or array thereof, relative to theme root.
* Defaults to 'editor-style.css'
function add_editor_style( $stylesheet = 'editor-style.css' ) {
add_theme_support( 'editor-style' );
$editor_styles = (array) $editor_styles;
$stylesheet = (array) $stylesheet;
$rtl_stylesheet = str_replace( '.css', '-rtl.css', $stylesheet[0] );
$stylesheet[] = $rtl_stylesheet;
$editor_styles = array_merge( $editor_styles, $stylesheet );
* Removes all visual editor stylesheets.
* @global array $editor_styles
* @return bool True on success, false if there were no stylesheets to remove.
function remove_editor_styles() {
if ( ! current_theme_supports( 'editor-style' ) ) {
_remove_theme_support( 'editor-style' );
$GLOBALS['editor_styles'] = array();
* Retrieves any registered editor stylesheet URLs.
* @global array $editor_styles Registered editor stylesheets
* @return string[] If registered, a list of editor stylesheet URLs.
function get_editor_stylesheets() {
// Load editor_style.css if the active theme supports it.
if ( ! empty( $GLOBALS['editor_styles'] ) && is_array( $GLOBALS['editor_styles'] ) ) {
$editor_styles = $GLOBALS['editor_styles'];
$editor_styles = array_unique( array_filter( $editor_styles ) );
$style_uri = get_stylesheet_directory_uri();
$style_dir = get_stylesheet_directory();
// Support externally referenced styles (like, say, fonts).
foreach ( $editor_styles as $key => $file ) {
if ( preg_match( '~^(https?:)?//~', $file ) ) {
$stylesheets[] = sanitize_url( $file );
unset( $editor_styles[ $key ] );
// Look in a parent theme first, that way child theme CSS overrides.
if ( is_child_theme() ) {
$template_uri = get_template_directory_uri();
$template_dir = get_template_directory();
foreach ( $editor_styles as $key => $file ) {
if ( $file && file_exists( "$template_dir/$file" ) ) {
$stylesheets[] = "$template_uri/$file";
foreach ( $editor_styles as $file ) {
if ( $file && file_exists( "$style_dir/$file" ) ) {
$stylesheets[] = "$style_uri/$file";
* Filters the array of URLs of stylesheets applied to the editor.
* @param string[] $stylesheets Array of URLs of stylesheets to be applied to the editor.
return apply_filters( 'editor_stylesheets', $stylesheets );
* Expands a theme's starter content configuration using core-provided data.
* @return array Array of starter content.
function get_theme_starter_content() {
$theme_support = get_theme_support( 'starter-content' );
if ( is_array( $theme_support ) && ! empty( $theme_support[0] ) && is_array( $theme_support[0] ) ) {
$config = $theme_support[0];
'text_business_info' => array(
'title' => _x( 'Find Us', 'Theme starter content' ),
'<strong>' . _x( 'Address', 'Theme starter content' ) . "</strong>\n",
_x( '123 Main Street', 'Theme starter content' ) . "\n",
_x( 'New York, NY 10001', 'Theme starter content' ) . "\n\n",
'<strong>' . _x( 'Hours', 'Theme starter content' ) . "</strong>\n",
_x( 'Monday–Friday: 9:00AM–5:00PM', 'Theme starter content' ) . "\n",
_x( 'Saturday & Sunday: 11:00AM–3:00PM', 'Theme starter content' ),
'title' => _x( 'About This Site', 'Theme starter content' ),
'text' => _x( 'This may be a good place to introduce yourself and your site or include some credits.', 'Theme starter content' ),
'title' => _x( 'Archives', 'Theme starter content' ),
'title' => _x( 'Calendar', 'Theme starter content' ),
'title' => _x( 'Categories', 'Theme starter content' ),
'title' => _x( 'Meta', 'Theme starter content' ),
'recent-comments' => array(
'title' => _x( 'Recent Comments', 'Theme starter content' ),
'title' => _x( 'Recent Posts', 'Theme starter content' ),
'title' => _x( 'Search', 'Theme starter content' ),
'title' => _x( 'Home', 'Theme starter content' ),
'url' => home_url( '/' ),
'page_home' => array( // Deprecated in favor of 'link_home'.
'object_id' => '{{home}}',
'object_id' => '{{about}}',
'object_id' => '{{blog}}',
'object_id' => '{{news}}',
'object_id' => '{{contact}}',
'title' => _x( 'Email', 'Theme starter content' ),
'url' => 'mailto:wordpress@example.com',
'link_facebook' => array(
'title' => _x( 'Facebook', 'Theme starter content' ),
'url' => 'https://www.facebook.com/wordpress',
'link_foursquare' => array(
'title' => _x( 'Foursquare', 'Theme starter content' ),
'url' => 'https://foursquare.com/',
'title' => _x( 'GitHub', 'Theme starter content' ),
'url' => 'https://github.com/wordpress/',
'link_instagram' => array(
'title' => _x( 'Instagram', 'Theme starter content' ),
'url' => 'https://www.instagram.com/explore/tags/wordcamp/',
'link_linkedin' => array(
'title' => _x( 'LinkedIn', 'Theme starter content' ),
'url' => 'https://www.linkedin.com/company/1089783',
'link_pinterest' => array(
'title' => _x( 'Pinterest', 'Theme starter content' ),
'url' => 'https://www.pinterest.com/',
'title' => _x( 'Twitter', 'Theme starter content' ),
'url' => 'https://twitter.com/wordpress',
'title' => _x( 'Yelp', 'Theme starter content' ),
'url' => 'https://www.yelp.com',
'title' => _x( 'YouTube', 'Theme starter content' ),
'url' => 'https://www.youtube.com/channel/UCdof4Ju7amm1chz1gi1T2ZA',
'post_title' => _x( 'Home', 'Theme starter content' ),
'post_content' => sprintf(
"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
_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' )
'post_title' => _x( 'About', 'Theme starter content' ),
'post_content' => sprintf(
"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
_x( 'You might be an artist who would like to introduce yourself and your work here or maybe you are a business with a mission to describe.', 'Theme starter content' )
'post_title' => _x( 'Contact', 'Theme starter content' ),
'post_content' => sprintf(
"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
_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' )
'post_title' => _x( 'Blog', 'Theme starter content' ),
'post_title' => _x( 'News', 'Theme starter content' ),
'homepage-section' => array(
'post_title' => _x( 'A homepage section', 'Theme starter content' ),
'post_content' => sprintf(
"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
_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' )
foreach ( $config as $type => $args ) {
// Use options and theme_mods as-is.
$content[ $type ] = $config[ $type ];