Make WordPress Core


Ignore:
Timestamp:
09/27/2017 10:24:37 PM (8 years ago)
Author:
westonruter
Message:

Customize: Introduce drafting and scheduling for Customizer changesets.

  • Incorporates code from the Customize Snapshots and Customize Posts feature plugins.
  • Adds a new Publish Settings section for managing the changeset status, scheduled date, and frontend preview link.
  • Updates Publish button to reflect the status selected in the Publish Settings (including Save Draft and Schedule).
  • Deactivates the Themes section when a non-publish status selected, and deactivates the Publish Settings section when previewing a theme switch.
  • Introduces an outer section type (wp.customize.OuterSection in JS) for the Publish Settings section to use and for available widgets and available nav menu panels to use in the future. These sections can be expanded while other sections are expanded.
  • Introduces WP_Customize_Date_Time_Control in PHP and wp.customize.DateTimeControl in JS for managing a date/time value.
  • Keeps track of scheduled time and proactively publish from the client when the time arrives, as opposed to waiting for WP Cron.
  • Auto-publishes a scheduled changeset when attempting to access one that missed its schedule.
  • Starts a new changeset if attempting to save a changeset that was previously publish.
  • Adds force arg to requestChangesetUpdate() to force an update request even when there are no pending changes.
  • Adds utils methods for getCurrentTimestamp and getRemainingTime.
  • Adds new state values for selectedChangesetStatus, changesetDate, selectedChangesetDate.
  • Fixes logic for when to short-circuit check to close Customizer when there are unsaved changes.
  • Adds getter methods for autosaved and branching parameters, with the latter applying the customize_changeset_branching filter.
  • Call to establish_loaded_changeset on the fly when changeset_uuid() is called if no changeset UUID was specififed.
  • De-duplicates logic for dismissing auto-draft changesets.
  • Includes unit tests.

Builds on [41597].
Props sayedwp, westonruter, melchoyce, JoshuaWold, folletto, stubgo, karmatosed, dlh, paaljoachim, afercia, johnregan3, utkarshpatel, valendesigns.
See #30937.
Fixes #39896, #28721, #39275.

File:
1 edited

Legend:

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

    r41603 r41626  
    597597     */
    598598    public function establish_loaded_changeset() {
     599        if ( empty( $this->_changeset_uuid ) ) {
     600            $changeset_uuid = null;
     601
     602            if ( ! $this->branching() ) {
     603                $unpublished_changeset_posts = $this->get_changeset_posts( array(
     604                    'post_status' => array_diff( get_post_stati(), array( 'auto-draft', 'publish', 'trash', 'inherit', 'private' ) ),
     605                    'exclude_restore_dismissed' => false,
     606                    'posts_per_page' => 1,
     607                    'order' => 'DESC',
     608                    'orderby' => 'date',
     609                ) );
     610                $unpublished_changeset_post = array_shift( $unpublished_changeset_posts );
     611                if ( ! empty( $unpublished_changeset_post ) && wp_is_uuid( $unpublished_changeset_post->post_name ) ) {
     612                    $changeset_uuid = $unpublished_changeset_post->post_name;
     613                }
     614            }
     615
     616            // If no changeset UUID has been set yet, then generate a new one.
     617            if ( empty( $changeset_uuid ) ) {
     618                $changeset_uuid = wp_generate_uuid4();
     619            }
     620
     621            $this->_changeset_uuid = $changeset_uuid;
     622        }
     623    }
     624
     625    /**
     626     * Callback to validate a theme once it is loaded
     627     *
     628     * @since 3.4.0
     629     */
     630    public function after_setup_theme() {
     631        $doing_ajax_or_is_customized = ( $this->doing_ajax() || isset( $_POST['customized'] ) );
     632        if ( ! $doing_ajax_or_is_customized && ! validate_current_theme() ) {
     633            wp_redirect( 'themes.php?broken=true' );
     634            exit;
     635        }
     636    }
     637
     638    /**
     639     * If the theme to be previewed isn't the active theme, add filter callbacks
     640     * to swap it out at runtime.
     641     *
     642     * @since 3.4.0
     643     */
     644    public function start_previewing_theme() {
     645        // Bail if we're already previewing.
     646        if ( $this->is_preview() ) {
     647            return;
     648        }
     649
     650        $this->previewing = true;
     651
     652        if ( ! $this->is_theme_active() ) {
     653            add_filter( 'template', array( $this, 'get_template' ) );
     654            add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
     655            add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
     656
     657            // @link: https://core.trac.wordpress.org/ticket/20027
     658            add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
     659            add_filter( 'pre_option_template', array( $this, 'get_template' ) );
     660
     661            // Handle custom theme roots.
     662            add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
     663            add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
     664        }
     665
     666        /**
     667         * Fires once the Customizer theme preview has started.
     668         *
     669         * @since 3.4.0
     670         *
     671         * @param WP_Customize_Manager $this WP_Customize_Manager instance.
     672         */
     673        do_action( 'start_previewing_theme', $this );
     674    }
     675
     676    /**
     677     * Stop previewing the selected theme.
     678     *
     679     * Removes filters to change the current theme.
     680     *
     681     * @since 3.4.0
     682     */
     683    public function stop_previewing_theme() {
     684        if ( ! $this->is_preview() ) {
     685            return;
     686        }
     687
     688        $this->previewing = false;
     689
     690        if ( ! $this->is_theme_active() ) {
     691            remove_filter( 'template', array( $this, 'get_template' ) );
     692            remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
     693            remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
     694
     695            // @link: https://core.trac.wordpress.org/ticket/20027
     696            remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
     697            remove_filter( 'pre_option_template', array( $this, 'get_template' ) );
     698
     699            // Handle custom theme roots.
     700            remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
     701            remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
     702        }
     703
     704        /**
     705         * Fires once the Customizer theme preview has stopped.
     706         *
     707         * @since 3.4.0
     708         *
     709         * @param WP_Customize_Manager $this WP_Customize_Manager instance.
     710         */
     711        do_action( 'stop_previewing_theme', $this );
     712    }
     713
     714    /**
     715     * Gets whether settings are or will be previewed.
     716     *
     717     * @since 4.9.0
     718     * @see WP_Customize_Setting::preview()
     719     *
     720     * @return bool
     721     */
     722    public function settings_previewed() {
     723        return $this->settings_previewed;
     724    }
     725
     726    /**
     727     * Gets whether data from a changeset's autosaved revision should be loaded if it exists.
     728     *
     729     * @since 4.9.0
     730     * @see WP_Customize_Manager::changeset_data()
     731     *
     732     * @return bool Is using autosaved changeset revision.
     733     */
     734    public function autosaved() {
     735        return $this->autosaved;
     736    }
     737
     738    /**
     739     * Whether the changeset branching is allowed.
     740     *
     741     * @since 4.9.0
     742     * @see WP_Customize_Manager::establish_loaded_changeset()
     743     *
     744     * @return bool Is changeset branching.
     745     */
     746    public function branching() {
    599747
    600748        /**
     
    625773        $this->branching = apply_filters( 'customize_changeset_branching', $this->branching, $this );
    626774
    627         if ( empty( $this->_changeset_uuid ) ) {
    628             $changeset_uuid = null;
    629 
    630             if ( ! $this->branching ) {
    631                 $unpublished_changeset_posts = $this->get_changeset_posts( array(
    632                     'post_status' => array_diff( get_post_stati(), array( 'auto-draft', 'publish', 'trash', 'inherit', 'private' ) ),
    633                     'exclude_restore_dismissed' => false,
    634                     'posts_per_page' => 1,
    635                     'order' => 'DESC',
    636                     'orderby' => 'date',
    637                 ) );
    638                 $unpublished_changeset_post = array_shift( $unpublished_changeset_posts );
    639                 if ( ! empty( $unpublished_changeset_post ) && wp_is_uuid( $unpublished_changeset_post->post_name ) ) {
    640                     $changeset_uuid = $unpublished_changeset_post->post_name;
    641                 }
    642             }
    643 
    644             // If no changeset UUID has been set yet, then generate a new one.
    645             if ( empty( $changeset_uuid ) ) {
    646                 $changeset_uuid = wp_generate_uuid4();
    647             }
    648 
    649             $this->_changeset_uuid = $changeset_uuid;
    650         }
    651     }
    652 
    653     /**
    654      * Callback to validate a theme once it is loaded
    655      *
    656      * @since 3.4.0
    657      */
    658     public function after_setup_theme() {
    659         $doing_ajax_or_is_customized = ( $this->doing_ajax() || isset( $_POST['customized'] ) );
    660         if ( ! $doing_ajax_or_is_customized && ! validate_current_theme() ) {
    661             wp_redirect( 'themes.php?broken=true' );
    662             exit;
    663         }
    664     }
    665 
    666     /**
    667      * If the theme to be previewed isn't the active theme, add filter callbacks
    668      * to swap it out at runtime.
    669      *
    670      * @since 3.4.0
    671      */
    672     public function start_previewing_theme() {
    673         // Bail if we're already previewing.
    674         if ( $this->is_preview() ) {
    675             return;
    676         }
    677 
    678         $this->previewing = true;
    679 
    680         if ( ! $this->is_theme_active() ) {
    681             add_filter( 'template', array( $this, 'get_template' ) );
    682             add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
    683             add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
    684 
    685             // @link: https://core.trac.wordpress.org/ticket/20027
    686             add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
    687             add_filter( 'pre_option_template', array( $this, 'get_template' ) );
    688 
    689             // Handle custom theme roots.
    690             add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
    691             add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
    692         }
    693 
    694         /**
    695          * Fires once the Customizer theme preview has started.
    696          *
    697          * @since 3.4.0
    698          *
    699          * @param WP_Customize_Manager $this WP_Customize_Manager instance.
    700          */
    701         do_action( 'start_previewing_theme', $this );
    702     }
    703 
    704     /**
    705      * Stop previewing the selected theme.
    706      *
    707      * Removes filters to change the current theme.
    708      *
    709      * @since 3.4.0
    710      */
    711     public function stop_previewing_theme() {
    712         if ( ! $this->is_preview() ) {
    713             return;
    714         }
    715 
    716         $this->previewing = false;
    717 
    718         if ( ! $this->is_theme_active() ) {
    719             remove_filter( 'template', array( $this, 'get_template' ) );
    720             remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
    721             remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );
    722 
    723             // @link: https://core.trac.wordpress.org/ticket/20027
    724             remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
    725             remove_filter( 'pre_option_template', array( $this, 'get_template' ) );
    726 
    727             // Handle custom theme roots.
    728             remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) );
    729             remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) );
    730         }
    731 
    732         /**
    733          * Fires once the Customizer theme preview has stopped.
    734          *
    735          * @since 3.4.0
    736          *
    737          * @param WP_Customize_Manager $this WP_Customize_Manager instance.
    738          */
    739         do_action( 'stop_previewing_theme', $this );
    740     }
    741 
    742     /**
    743      * Gets whether settings are or will be previewed.
    744      *
    745      * @since 4.9.0
    746      * @see WP_Customize_Setting::preview()
    747      *
    748      * @return bool
    749      */
    750     public function settings_previewed() {
    751         return $this->settings_previewed;
     775        return $this->branching;
    752776    }
    753777
     
    764788    public function changeset_uuid() {
    765789        if ( empty( $this->_changeset_uuid ) ) {
    766             throw new Exception( 'Changeset UUID has not been set.' ); // @todo Replace this with a call to `WP_Customize_Manager::establish_loaded_changeset()` during 4.9-beta2.
     790            $this->establish_loaded_changeset();
    767791        }
    768792        return $this->_changeset_uuid;
     
    9821006
    9831007    /**
     1008     * Dismiss all of the current user's auto-drafts (other than the present one).
     1009     *
     1010     * @since 4.9.0
     1011     * @return int The number of auto-drafts that were dismissed.
     1012     */
     1013    protected function dismiss_user_auto_draft_changesets() {
     1014        $changeset_autodraft_posts = $this->get_changeset_posts( array(
     1015            'post_status' => 'auto-draft',
     1016            'exclude_restore_dismissed' => true,
     1017            'posts_per_page' => -1,
     1018        ) );
     1019        $dismissed = 0;
     1020        foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
     1021            if ( $autosave_autodraft_post->ID === $this->changeset_post_id() ) {
     1022                continue;
     1023            }
     1024            if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) {
     1025                $dismissed++;
     1026            }
     1027        }
     1028        return $dismissed;
     1029    }
     1030
     1031    /**
    9841032     * Get the changeset post id for the loaded changeset.
    9851033     *
     
    10511099            $this->_changeset_data = array();
    10521100        } else {
    1053             if ( $this->autosaved ) {
     1101            if ( $this->autosaved() ) {
    10541102                $autosave_post = wp_get_post_autosave( $changeset_post_id );
    10551103                if ( $autosave_post ) {
     
    19732021            'changeset' => array(
    19742022                'uuid' => $this->changeset_uuid(),
    1975                 'autosaved' => $this->autosaved,
     2023                'autosaved' => $this->autosaved(),
    19762024            ),
    19772025            'timeouts' => array(
     
    23462394        } else {
    23472395            $response = $r;
     2396            $changeset_post = get_post( $this->changeset_post_id() );
    23482397
    23492398            // Dismiss all other auto-draft changeset posts for this user (they serve like autosave revisions), as there should only be one.
    23502399            if ( $is_new_changeset ) {
    2351                 $changeset_autodraft_posts = $this->get_changeset_posts( array(
    2352                     'post_status' => 'auto-draft',
    2353                     'exclude_restore_dismissed' => true,
    2354                     'posts_per_page' => -1,
    2355                 ) );
    2356                 foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
    2357                     if ( $autosave_autodraft_post->ID !== $this->changeset_post_id() ) {
    2358                         update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true );
    2359                     }
    2360                 }
     2400                $this->dismiss_user_auto_draft_changesets();
    23612401            }
    23622402
    23632403            // Note that if the changeset status was publish, then it will get set to trash if revisions are not supported.
    2364             $response['changeset_status'] = get_post_status( $this->changeset_post_id() );
     2404            $response['changeset_status'] = $changeset_post->post_status;
    23652405            if ( $is_publish && 'trash' === $response['changeset_status'] ) {
    23662406                $response['changeset_status'] = 'publish';
    23672407            }
    23682408
    2369             if ( 'publish' === $response['changeset_status'] ) {
     2409            if ( 'future' === $response['changeset_status'] ) {
     2410                $response['changeset_date'] = $changeset_post->post_date;
     2411            }
     2412
     2413            if ( 'publish' === $response['changeset_status'] || 'trash' === $response['changeset_status'] ) {
    23702414                $response['next_changeset_uuid'] = wp_generate_uuid4();
    23712415            }
     
    24352479            $existing_status = get_post_status( $changeset_post_id );
    24362480            if ( 'publish' === $existing_status || 'trash' === $existing_status ) {
    2437                 return new WP_Error( 'changeset_already_published' );
     2481                return new WP_Error(
     2482                    'changeset_already_published',
     2483                    __( 'The previous set of changes already been published. Please try saving your current set of changes again.' ),
     2484                    array(
     2485                        'next_changeset_uuid' => wp_generate_uuid4(),
     2486                    )
     2487                );
    24382488            }
    24392489
     
    24542504            $is_future_dated = ( mysql2date( 'U', $args['date_gmt'], false ) > mysql2date( 'U', $now, false ) );
    24552505            if ( ! $is_future_dated ) {
    2456                 return new WP_Error( 'not_future_date' ); // Only future dates are allowed.
     2506                return new WP_Error( 'not_future_date', __( 'You must supply a future date to schedule.' ) ); // Only future dates are allowed.
    24572507            }
    24582508
     
    24692519            $changeset_post = get_post( $changeset_post_id );
    24702520            if ( mysql2date( 'U', $changeset_post->post_date_gmt, false ) <= mysql2date( 'U', $now, false ) ) {
    2471                 return new WP_Error( 'not_future_date' );
     2521                return new WP_Error( 'not_future_date', __( 'You must supply a future date to schedule.' ) );
    24722522            }
    24732523        }
     
    30573107
    30583108        if ( empty( $changeset_post_id ) || 'auto-draft' === get_post_status( $changeset_post_id ) ) {
    3059             $changeset_autodraft_posts = $this->get_changeset_posts( array(
    3060                 'post_status' => 'auto-draft',
    3061                 'exclude_restore_dismissed' => true,
    3062                 'posts_per_page' => -1,
    3063             ) );
    3064             $dismissed = 0;
    3065             foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
    3066                 if ( $autosave_autodraft_post->ID === $changeset_post_id ) {
    3067                     continue;
    3068                 }
    3069                 if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) {
    3070                     $dismissed++;
    3071                 }
    3072             }
     3109            $dismissed = $this->dismiss_user_auto_draft_changesets();
    30733110            if ( $dismissed > 0 ) {
    30743111                wp_send_json_success( 'auto_draft_dismissed' );
    30753112            } else {
    3076                 wp_send_json_error( 'no_autosave_to_delete', 404 );
     3113                wp_send_json_error( 'no_auto_draft_to_delete', 404 );
    30773114            }
    30783115        } else {
     
    30903127                }
    30913128            } else {
    3092                 wp_send_json_error( 'no_autosave_to_delete', 404 );
     3129                wp_send_json_error( 'no_autosave_revision_to_delete', 404 );
    30933130            }
    30943131        }
     
    35173554            </ul>
    35183555        </script>
     3556        <script type="text/html" id="tmpl-customize-preview-link-control" >
     3557            <span class="customize-control-title">
     3558                <label><?php esc_html_e( 'Share Preview Link' ); ?></label>
     3559            </span>
     3560            <span class="description customize-control-description"><?php esc_html_e( 'See how changes would look live on your website, and share the preview with people who can\'t access the Customizer.' ); ?></span>
     3561            <div class="customize-control-notifications-container"></div>
     3562            <div class="preview-link-wrapper">
     3563                <label>
     3564                    <span class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></span>
     3565                    <a class="preview-control-element" data-component="link" href="" target=""></a>
     3566                    <input readonly class="preview-control-element" data-component="input" value="test" >
     3567                    <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button>
     3568                </label>
     3569            </div>
     3570        </script>
    35193571        <?php
    35203572    }
     
    38783930        $autosave_autodraft_post = null;
    38793931        $changeset_post_id = $this->changeset_post_id();
    3880         if ( ! $this->saved_starter_content_changeset && ! $this->autosaved ) {
     3932        if ( ! $this->saved_starter_content_changeset && ! $this->autosaved() ) {
    38813933            if ( $changeset_post_id ) {
    38823934                $autosave_revision_post = wp_get_post_autosave( $changeset_post_id );
     
    38943946
    38953947        // Prepare Customizer settings to pass to JavaScript.
     3948        $changeset_post = null;
     3949        if ( $changeset_post_id ) {
     3950            $changeset_post = get_post( $changeset_post_id );
     3951        }
     3952
    38963953        $settings = array(
    38973954            'changeset' => array(
    38983955                'uuid' => $this->changeset_uuid(),
    3899                 'branching' => $this->branching,
    3900                 'autosaved' => $this->autosaved,
     3956                'branching' => $this->branching(),
     3957                'autosaved' => $this->autosaved(),
    39013958                'hasAutosaveRevision' => ! empty( $autosave_revision_post ),
    39023959                'latestAutoDraftUuid' => $autosave_autodraft_post ? $autosave_autodraft_post->post_name : null,
    3903                 'status' => $changeset_post_id ? get_post_status( $changeset_post_id ) : '',
     3960                'status' => $changeset_post ? $changeset_post->post_status : '',
     3961                'currentUserCanPublish' => current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ),
     3962                'publishDate' => $changeset_post ? $changeset_post->post_date : '', // @todo Only if future status? Rename to just date?
    39043963            ),
     3964            'initialServerDate' => current_time( 'mysql', false ),
     3965            'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
     3966            'initialClientTimestamp' => -1, // To be set with JS below.
    39053967            'timeouts' => array(
    39063968                'windowRefresh' => 250,
     
    39584020        <script type="text/javascript">
    39594021            var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
     4022            _wpCustomizeSettings.initialClientTimestamp = _.now();
    39604023            _wpCustomizeSettings.controls = {};
    39614024            _wpCustomizeSettings.settings = {};
     
    40484111        $this->register_control_type( 'WP_Customize_Theme_Control' );
    40494112        $this->register_control_type( 'WP_Customize_Code_Editor_Control' );
     4113        $this->register_control_type( 'WP_Customize_Date_Time_Control' );
     4114
     4115        /* Publish Settings */
     4116
     4117        $this->add_section( 'publish_settings', array(
     4118            'title' => __( 'Publish Settings' ),
     4119            'priority' => 0,
     4120            'capability' => 'customize',
     4121            'type' => 'outer',
     4122            'active_callback' => array( $this, 'is_theme_active' ),
     4123        ) );
     4124
     4125        /* Publish Settings Controls */
     4126        $status_choices = array(
     4127            'publish' => __( 'Publish' ),
     4128            'draft' => __( 'Save Draft' ),
     4129            'future' => __( 'Schedule' ),
     4130        );
     4131
     4132        if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
     4133            unset( $status_choices['publish'] );
     4134        }
     4135
     4136        $this->add_control( 'changeset_status', array(
     4137            'section' => 'publish_settings',
     4138            'settings' => array(),
     4139            'type' => 'radio',
     4140            'label' => __( 'Action' ),
     4141            'choices' => $status_choices,
     4142            'capability' => 'customize',
     4143        ) );
     4144
     4145        if ( $this->changeset_post_id() && 'future' === get_post_status( $this->changeset_post_id() ) ) {
     4146            $initial_date = get_the_time( 'Y-m-d H:i:s', $this->changeset_post_id() );
     4147        } else {
     4148            $initial_date = current_time( 'mysql', false );
     4149        }
     4150        $this->add_control( new WP_Customize_Date_Time_Control( $this, 'changeset_scheduled_date', array(
     4151            'section' => 'publish_settings',
     4152            'settings' => array(),
     4153            'type' => 'date_time',
     4154            'min_year' => date( 'Y' ),
     4155            'allow_past_date' => false,
     4156            'twelve_hour_format' => false !== stripos( get_option( 'time_format' ), 'a' ),
     4157            'description' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ),
     4158            'capability' => 'customize',
     4159            'default_value' => $initial_date,
     4160        ) ) );
    40504161
    40514162        /* Themes */
Note: See TracChangeset for help on using the changeset viewer.