Make WordPress Core


Ignore:
Timestamp:
10/28/2016 02:56:16 AM (10 years ago)
Author:
westonruter
Message:

Customize: Introduce starter content and site freshness state.

A theme can opt-in for tailored starter content to apply to the customizer when previewing the theme on a fresh install, when fresh_site is at its initial 1 value. Starter content is staged in the customizer and does not go live unless the changes are published. Initial starter content is added to Twenty Seventeen.

  • The fresh_site flag is cleared when a published post or page is saved, when widgets are modified, or when the customizer state is saved.
  • Starter content is registered via starter-content theme support, where the argument is an array containing widgets, posts, nav_menus, options, and theme_mods. Posts/pages in starter content are created with the auto-draft status, re-using the page/post stubs feature added to nav menus and the static front page controls.
  • A get_theme_starter_content filter allows for plugins to extend a theme's starter content.
  • Starter content in themes can/should re-use existing starter content items in core by using named placeholders.
  • Import theme starter content into customized state when fresh site.
  • Prevent original_title differences from causing refreshes if title is present.
  • Ensure nav menu item url is set according to object when previewing.
  • Make sure initial saved state is false if there are dirty settings without an existing changeset.
  • Ensure dirty settings are cleaned upon changeset publishing.

Props helen, westonruter, ocean90.
Fixes #38114, #38533.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r38989 r38991  
    532532                }
    533533
     534                // Import theme starter content for fresh installs when landing in the customizer and no existing changeset loaded.
     535                if ( get_option( 'fresh_site' ) && 'customize.php' === $pagenow && ! $this->changeset_post_id() ) {
     536                        add_action( 'after_setup_theme', array( $this, 'import_theme_starter_content' ), 100 );
     537                }
     538
    534539                $this->start_previewing_theme();
    535540        }
    … …  
    886891                }
    887892                return $this->_changeset_data;
     893        }
     894
     895        /**
     896         * Import theme starter content into post values.
     897         *
     898         * @since 4.7.0
     899         * @access public
     900         *
     901         * @param array $starter_content Starter content. Defaults to `get_theme_starter_content()`.
     902         */
     903        function import_theme_starter_content( $starter_content = array() ) {
     904                if ( empty( $starter_content ) ) {
     905                        $starter_content = get_theme_starter_content();
     906                }
     907
     908                $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array();
     909                $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array();
     910                $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array();
     911                $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array();
     912                $theme_mods = isset( $starter_content['theme_mods'] ) ? $starter_content['theme_mods'] : array();
     913
     914                // Widgets.
     915                $max_widget_numbers = array();
     916                foreach ( $sidebars_widgets as $sidebar_id => $widgets ) {
     917                        $sidebar_widget_ids = array();
     918                        foreach ( $widgets as $widget ) {
     919                                list( $id_base, $instance ) = $widget;
     920
     921                                if ( ! isset( $max_widget_numbers[ $id_base ] ) ) {
     922
     923                                        // When $settings is an array-like object, get an intrinsic array for use with array_keys().
     924                                        $settings = get_option( "widget_{$id_base}", array() );
     925                                        if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) {
     926                                                $settings = $settings->getArrayCopy();
     927                                        }
     928
     929                                        // Find the max widget number for this type.
     930                                        $widget_numbers = array_keys( $settings );
     931                                        $widget_numbers[] = 1;
     932                                        $max_widget_numbers[ $id_base ] = call_user_func_array( 'max', $widget_numbers );
     933                                }
     934                                $max_widget_numbers[ $id_base ] += 1;
     935
     936                                $widget_id = sprintf( '%s-%d', $id_base, $max_widget_numbers[ $id_base ] );
     937                                $setting_id = sprintf( 'widget_%s[%d]', $id_base, $max_widget_numbers[ $id_base ] );
     938
     939                                $class = 'WP_Customize_Setting';
     940
     941                                /** This filter is documented in wp-includes/class-wp-customize-manager.php */
     942                                $args = apply_filters( 'customize_dynamic_setting_args', false, $setting_id );
     943
     944                                if ( false !== $args ) {
     945
     946                                        /** This filter is documented in wp-includes/class-wp-customize-manager.php */
     947                                        $class = apply_filters( 'customize_dynamic_setting_class', $class, $setting_id, $args );
     948
     949                                        $setting = new $class( $this, $setting_id, $args );
     950                                        $setting_value = call_user_func( $setting->sanitize_js_callback, $instance, $setting );
     951                                        $this->set_post_value( $setting_id, $setting_value );
     952                                        $sidebar_widget_ids[] = $widget_id;
     953                                }
     954                        }
     955
     956                        $this->set_post_value( sprintf( 'sidebars_widgets[%s]', $sidebar_id ), $sidebar_widget_ids );
     957                }
     958
     959                // Posts & pages.
     960                if ( ! empty( $posts ) ) {
     961                        foreach ( array_keys( $posts ) as $post_symbol ) {
     962                                $posts[ $post_symbol ]['ID'] = wp_insert_post( wp_slash( array_merge(
     963                                        $posts[ $post_symbol ],
     964                                        array( 'post_status' => 'auto-draft' )
     965                                ) ) );
     966                        }
     967                        $this->set_post_value( 'nav_menus_created_posts', wp_list_pluck( $posts, 'ID' ) ); // This is why nav_menus component is dependency for adding posts.
     968                }
     969
     970                // Nav menus.
     971                $placeholder_id = -1;
     972                foreach ( $nav_menus as $nav_menu_location => $nav_menu ) {
     973                        $nav_menu_term_id = $placeholder_id--;
     974                        $nav_menu_setting_id = sprintf( 'nav_menu[%d]', $nav_menu_term_id );
     975                        $this->set_post_value( $nav_menu_setting_id, array(
     976                                'name' => isset( $nav_menu['name'] ) ? $nav_menu['name'] : $nav_menu_location,
     977                        ) );
     978
     979                        // @todo Add support for menu_item_parent.
     980                        $position = 0;
     981                        foreach ( $nav_menu['items'] as $nav_menu_item ) {
     982                                $nav_menu_item_setting_id = sprintf( 'nav_menu_item[%d]', $placeholder_id-- );
     983                                if ( ! isset( $nav_menu_item['position'] ) ) {
     984                                        $nav_menu_item['position'] = $position++;
     985                                }
     986                                $nav_menu_item['nav_menu_term_id'] = $nav_menu_term_id;
     987
     988                                if ( isset( $nav_menu_item['object_id'] ) ) {
     989                                        if ( 'post_type' === $nav_menu_item['type'] && preg_match( '/^{{(?P<symbol>.+)}}$/', $nav_menu_item['object_id'], $matches ) && isset( $posts[ $matches['symbol'] ] ) ) {
     990                                                $nav_menu_item['object_id'] = $posts[ $matches['symbol'] ]['ID'];
     991                                                if ( empty( $nav_menu_item['title'] ) ) {
     992                                                        $original_object = get_post( $nav_menu_item['object_id'] );
     993                                                        $nav_menu_item['title'] = $original_object->post_title;
     994                                                }
     995                                        } else {
     996                                                continue;
     997                                        }
     998                                } else {
     999                                        $nav_menu_item['object_id'] = 0;
     1000                                }
     1001                                $this->set_post_value( $nav_menu_item_setting_id, $nav_menu_item );
     1002                        }
     1003
     1004                        $this->set_post_value( sprintf( 'nav_menu_locations[%s]', $nav_menu_location ), $nav_menu_term_id );
     1005                }
     1006
     1007                // Options.
     1008                foreach ( $options as $name => $value ) {
     1009                        if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) && isset( $posts[ $matches['symbol'] ] ) ) {
     1010                                $value = $posts[ $matches['symbol'] ]['ID'];
     1011                        }
     1012                        $this->set_post_value( $name, $value );
     1013                }
     1014
     1015                // Theme mods.
     1016                foreach ( $theme_mods as $name => $value ) {
     1017                        if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) && isset( $posts[ $matches['symbol'] ] ) ) {
     1018                                $value = $posts[ $matches['symbol'] ]['ID'];
     1019                        }
     1020                        $this->set_post_value( $name, $value );
     1021                }
    8881022        }
    8891023
Note: See TracChangeset for help on using the changeset viewer.