Make WordPress Core

Changeset 41750


Ignore:
Timestamp:
10/04/2017 08:01:12 PM (7 years ago)
Author:
westonruter
Message:

Customize: Allow controls to be created with pre-instantiated Setting object(s), or even with plain Value object(s).

  • Allow passing settings in keyed object (e.g. settings: { default: 'id' } ), or as an array (e.g. settings: [ 'id' ]) with first being default; again, Setting/Value` objects may be supplied instead of IDs.
  • Allow a single setting to be supplied with just a single setting param, either a string or a Setting/Value object.
  • Update changeset_status and scheduled_changeset_date to be added dynamically with JS and simply passing of api.state() instances as setting.
  • Introduce a data-customize-setting-key-link attribute which, unlike data-customize-setting-link, allows passing the setting key (e.g. default) as opposed to the setting ID.
  • Allow WP_Customize_Control::get_link() to return data-customize-setting-key-link when setting is not registered.
  • Eliminate default_value from WP_Customize_Date_Time_Control since now comes from supplied Value.
  • Export status choices as wp.customize.settings.changeset.statusChoices.
  • Export date and time formats as wp.customize.settings.dateFormat and wp.customize.settings.timeFormat respectively.

Props westonruter, sayedwp.
See #39896, #30738, #30741, #42083.
Fixes #37964, #36167.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/customize-controls.css

    r41740 r41750  
    139139}
    140140
    141 #customize-control-changeset_status label,
     141#customize-control-changeset_status .customize-inside-control-row,
    142142#customize-control-changeset_preview_link input {
    143143    background-color: #ffffff;
     
    171171}
    172172
    173 #customize-control-changeset_status label {
     173#customize-control-changeset_status .customize-inside-control-row {
    174174    padding-top: 10px;
    175175    padding-bottom: 10px;
     
    177177}
    178178
    179 #customize-control-changeset_status label:first-of-type {
     179#customize-control-changeset_status .customize-inside-control-row:first-of-type {
    180180    border-top: 1px solid #ddd;
    181181}
     
    28102810    }
    28112811
    2812     #customize-control-changeset_status label {
     2812    #customize-control-changeset_status .customize-inside-control-row {
    28132813        padding-top: 15px;
    28142814    }
  • trunk/src/wp-admin/js/customize-controls.js

    r41739 r41750  
    30953095     * @param {string} [options.active=true]    - Whether the control is active.
    30963096     * @param {string} options.section          - The ID of the section the control belongs to.
    3097      * @param {string} options.settings.default - The ID of the setting the control relates to.
    3098      * @param {string} options.settings.data
     3097     * @param {mixed}  [options.setting]        - The ID of the main setting or an instance of this setting.
     3098     * @param {mixed}  options.settings         - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects.   
     3099     * @param {mixed}  options.settings.default - The ID of the setting the control relates to.
     3100     * @param {string} options.settings.data    - @todo Is this used?
    30993101     * @param {string} options.label            - Label.
    31003102     * @param {string} options.description      - Description.
     
    31113113
    31123114        initialize: function( id, options ) {
    3113             var control = this,
    3114                 nodes, radios, settings;
     3115            var control = this, deferredSettingIds = [], settings, gatherSettings;
    31153116
    31163117            control.params = _.extend( {}, control.defaults );
     
    31223123            if ( ! control.params.instanceNumber ) {
    31233124                control.params.instanceNumber = api.Control.instanceCounter;
     3125            }
     3126
     3127            // Look up the type if one was not supplied.
     3128            if ( ! control.params.type ) {
     3129                _.find( api.controlConstructor, function( Constructor, type ) {
     3130                    if ( Constructor === control.constructor ) {
     3131                        control.params.type = type;
     3132                        return true;
     3133                    }
     3134                    return false;
     3135                } );
    31243136            }
    31253137
     
    31543166            control.elements = [];
    31553167
    3156             nodes  = control.container.find('[data-customize-setting-link]');
    3157             radios = {};
    3158 
    3159             nodes.each( function() {
    3160                 var node = $( this ),
    3161                     name;
    3162 
    3163                 if ( node.is( ':radio' ) ) {
    3164                     name = node.prop( 'name' );
    3165                     if ( radios[ name ] ) {
    3166                         return;
    3167                     }
    3168 
    3169                     radios[ name ] = true;
    3170                     node = nodes.filter( '[name="' + name + '"]' );
    3171                 }
    3172 
    3173                 api( node.data( 'customizeSettingLink' ), function( setting ) {
    3174                     var element = new api.Element( node );
    3175                     control.elements.push( element );
    3176                     element.sync( setting );
    3177                     element.set( setting() );
    3178                 });
    3179             });
    3180 
    31813168            control.active.bind( function ( active ) {
    31823169                var args = control.activeArgumentsQueue.shift();
     
    31913178            api.utils.bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] );
    31923179
    3193             /*
    3194              * After all settings related to the control are available,
    3195              * make them available on the control and embed the control into the page.
    3196              */
    3197             settings = $.map( control.params.settings, function( value ) {
    3198                 return value;
    3199             });
    3200 
    3201             if ( 0 === settings.length ) {
    3202                 control.setting = null;
    3203                 control.settings = {};
     3180            control.settings = {};
     3181
     3182            settings = {};
     3183            if ( control.params.setting ) {
     3184                settings['default'] = control.params.setting;
     3185            }
     3186            _.extend( settings, control.params.settings );
     3187
     3188            // Note: Settings can be an array or an object.
     3189            _.each( settings, function( setting, key ) {
     3190                if ( _.isObject( setting ) ) { // @todo Or check if instance of api.Setting?
     3191                    control.settings[ key ] = setting;
     3192                } else {
     3193                    deferredSettingIds.push( setting );
     3194                }
     3195            } );
     3196
     3197            gatherSettings = function() {
     3198
     3199                // Fill-in all resolved settings.
     3200                _.each( settings, function ( settingId, key ) {
     3201                    if ( ! control.settings[ key ] && _.isString( settingId ) ) {
     3202                        control.settings[ key ] = api( settingId );
     3203                    }
     3204                } );
     3205
     3206                // Make sure settings passed as array gets associated with default.
     3207                if ( control.settings[0] && ! control.settings['default'] ) {
     3208                    control.settings['default'] = control.settings[0];
     3209                }
     3210
     3211                // Identify the main setting.
     3212                control.setting = control.settings['default'] || null;
     3213
    32043214                control.embed();
     3215            };
     3216
     3217            if ( 0 === deferredSettingIds.length ) {
     3218                gatherSettings();
    32053219            } else {
    3206                 api.apply( api, settings.concat( function() {
    3207                     var key;
    3208 
    3209                     control.settings = {};
    3210                     for ( key in control.params.settings ) {
    3211                         control.settings[ key ] = api( control.params.settings[ key ] );
    3212                     }
    3213 
    3214                     control.setting = control.settings['default'] || null;
    3215 
    3216                     // Add setting notifications to the control notification.
    3217                     _.each( control.settings, function( setting ) {
    3218                         setting.notifications.bind( 'add', function( settingNotification ) {
    3219                             var params = _.extend(
    3220                                 {},
    3221                                 settingNotification,
    3222                                 {
    3223                                     setting: setting.id
    3224                                 }
    3225                             );
    3226                             control.notifications.add( new api.Notification( setting.id + ':' + settingNotification.code, params ) );
    3227                         } );
    3228                         setting.notifications.bind( 'remove', function( settingNotification ) {
    3229                             control.notifications.remove( setting.id + ':' + settingNotification.code );
    3230                         } );
    3231                     } );
    3232 
    3233                     control.embed();
    3234                 }) );
     3220                api.apply( api, deferredSettingIds.concat( gatherSettings ) );
    32353221            }
    32363222
    32373223            // After the control is embedded on the page, invoke the "ready" method.
    32383224            control.deferred.embedded.done( function () {
     3225                control.linkElements();
    32393226                control.setupNotifications();
    32403227                control.ready();
    32413228            });
     3229        },
     3230
     3231        /**
     3232         * Link elements between settings and inputs.
     3233         *
     3234         * @since 4.7.0
     3235         * @access public
     3236         *
     3237         * @returns {void}
     3238         */
     3239        linkElements: function () {
     3240            var control = this, nodes, radios, element;
     3241
     3242            nodes = control.container.find( '[data-customize-setting-link], [data-customize-setting-key-link]' );
     3243            radios = {};
     3244
     3245            nodes.each( function () {
     3246                var node = $( this ), name, setting;
     3247
     3248                if ( node.data( 'customizeSettingLinked' ) ) {
     3249                    return;
     3250                }
     3251                node.data( 'customizeSettingLinked', true ); // Prevent re-linking element.
     3252
     3253                if ( node.is( ':radio' ) ) {
     3254                    name = node.prop( 'name' );
     3255                    if ( radios[name] ) {
     3256                        return;
     3257                    }
     3258
     3259                    radios[name] = true;
     3260                    node = nodes.filter( '[name="' + name + '"]' );
     3261                }
     3262
     3263                // Let link by default refer to setting ID. If it doesn't exist, fallback to looking up by setting key.
     3264                if ( node.data( 'customizeSettingLink' ) ) {
     3265                    setting = api( node.data( 'customizeSettingLink' ) );
     3266                } else if ( node.data( 'customizeSettingKeyLink' ) ) {
     3267                    setting = control.settings[ node.data( 'customizeSettingKeyLink' ) ];
     3268                }
     3269
     3270                if ( setting ) {
     3271                    element = new api.Element( node );
     3272                    control.elements.push( element );
     3273                    element.sync( setting );
     3274                    element.set( setting() );
     3275                }
     3276            } );
    32423277        },
    32433278
     
    33423377        setupNotifications: function() {
    33433378            var control = this, renderNotificationsIfVisible, onSectionAssigned;
     3379
     3380            // Add setting notifications to the control notification.
     3381            _.each( control.settings, function( setting ) {
     3382                if ( ! setting.notifications ) {
     3383                    return;
     3384                }
     3385                setting.notifications.bind( 'add', function( settingNotification ) {
     3386                    var params = _.extend(
     3387                        {},
     3388                        settingNotification,
     3389                        {
     3390                            setting: setting.id
     3391                        }
     3392                    );
     3393                    control.notifications.add( new api.Notification( setting.id + ':' + settingNotification.code, params ) );
     3394                } );
     3395                setting.notifications.bind( 'remove', function( settingNotification ) {
     3396                    control.notifications.remove( setting.id + ':' + settingNotification.code );
     3397                } );
     3398            } );
    33443399
    33453400            control.notifications.container = control.getNotificationsContainerElement();
     
    49875042            _.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'updateMinutesForHour', 'populateDateInputs' );
    49885043
    4989             // @todo This needs https://core.trac.wordpress.org/ticket/37964
    49905044            if ( ! control.setting ) {
    4991                 control.setting = new api.Value();
    4992             }
    4993 
    4994             // @todo Should this be? Default should be on client. The default value should be in the setting itself.
    4995             if ( ! control.setting.get() && control.params.defaultValue ) {
    4996                 control.setting.set( control.params.defaultValue );
     5045                throw new Error( 'Missing setting' );
    49975046            }
    49985047
     
    63616410            footerActions = $( '#customize-footer-actions' );
    63626411
     6412        // Set up publish settings section and its controls.
    63636413        api.section( 'publish_settings', function( section ) {
    6364             var updateButtonsState, trashControl, updateSectionActive, isSectionActive;
     6414            var updateButtonsState, trashControl, updateSectionActive, isSectionActive, statusControl, dateControl, toggleDateControl, publishWhenTime, pollInterval, updateTimeArrivedPoller, timeArrivedPollingInterval = 1000;
    63656415
    63666416            trashControl = new api.Control( 'trash_changeset', {
     
    64336483                publishSettingsBtn.attr( 'aria-expanded', String( isExpanded ) );
    64346484                publishSettingsBtn.toggleClass( 'active', isExpanded );
     6485            } );
     6486
     6487            statusControl = new api.Control( 'changeset_status', {
     6488                priority: 10,
     6489                type: 'radio',
     6490                section: 'publish_settings',
     6491                setting: api.state( 'selectedChangesetStatus' ),
     6492                templateId: 'customize-selected-changeset-status-control',
     6493                label: api.l10n.action,
     6494                choices: api.settings.changeset.statusChoices
     6495            } );
     6496            api.control.add( statusControl );
     6497
     6498            dateControl = new api.DateTimeControl( 'changeset_scheduled_date', {
     6499                priority: 20,
     6500                section: 'publish_settings',
     6501                setting: api.state( 'selectedChangesetDate' ),
     6502                minYear: ( new Date() ).getFullYear(),
     6503                allowPastDate: false,
     6504                includeTime: true,
     6505                twelveHourFormat: /a/i.test( api.settings.timeFormat ),
     6506                description: api.l10n.scheduleDescription
     6507            } );
     6508            dateControl.notifications.alt = true;
     6509            api.control.add( dateControl );
     6510
     6511            publishWhenTime = function() {
     6512                api.state( 'selectedChangesetStatus' ).set( 'publish' );
     6513                api.previewer.save();
     6514            };
     6515
     6516            // Start countdown for when the dateTime arrives, or clear interval when it is .
     6517            updateTimeArrivedPoller = function() {
     6518                var shouldPoll = (
     6519                    'future' === api.state( 'changesetStatus' ).get() &&
     6520                    'future' === api.state( 'selectedChangesetStatus' ).get() &&
     6521                    api.state( 'changesetDate' ).get() &&
     6522                    api.state( 'selectedChangesetDate' ).get() === api.state( 'changesetDate' ).get() &&
     6523                    api.utils.getRemainingTime( api.state( 'changesetDate' ).get() ) >= 0
     6524                );
     6525
     6526                if ( shouldPoll && ! pollInterval ) {
     6527                    pollInterval = setInterval( function() {
     6528                        var remainingTime = api.utils.getRemainingTime( api.state( 'changesetDate' ).get() );
     6529                        api.state( 'remainingTimeToPublish' ).set( remainingTime );
     6530                        if ( remainingTime <= 0 ) {
     6531                            clearInterval( pollInterval );
     6532                            pollInterval = 0;
     6533                            publishWhenTime();
     6534                        }
     6535                    }, timeArrivedPollingInterval );
     6536                } else if ( ! shouldPoll && pollInterval ) {
     6537                    clearInterval( pollInterval );
     6538                    pollInterval = 0;
     6539                }
     6540            };
     6541
     6542            api.state( 'changesetDate' ).bind( updateTimeArrivedPoller );
     6543            api.state( 'selectedChangesetDate' ).bind( updateTimeArrivedPoller );
     6544            api.state( 'changesetStatus' ).bind( updateTimeArrivedPoller );
     6545            api.state( 'selectedChangesetStatus' ).bind( updateTimeArrivedPoller );
     6546            updateTimeArrivedPoller();
     6547
     6548            // Ensure dateControl only appears when selected status is future.
     6549            dateControl.active.validate = function() {
     6550                return 'future' === api.state( 'selectedChangesetStatus' ).get();
     6551            };
     6552            toggleDateControl = function( value ) {
     6553                dateControl.active.set( 'future' === value );
     6554            };
     6555            toggleDateControl( api.state( 'selectedChangesetStatus' ).get() );
     6556            api.state( 'selectedChangesetStatus' ).bind( toggleDateControl );
     6557
     6558            // Show notification on date control when status is future but it isn't a future date.
     6559            api.state( 'saving' ).bind( function( isSaving ) {
     6560                if ( isSaving && 'future' === api.state( 'selectedChangesetStatus' ).get() ) {
     6561                    dateControl.toggleFutureDateNotification( ! dateControl.isFutureDate() );
     6562                }
    64356563            } );
    64366564        } );
     
    70637191            changesetStatus( api.settings.changeset.status );
    70647192            changesetDate( api.settings.changeset.publishDate );
     7193            selectedChangesetDate( api.settings.changeset.publishDate );
    70657194            selectedChangesetStatus( '' === api.settings.changeset.status || 'auto-draft' === api.settings.changeset.status ? 'publish' : api.settings.changeset.status );
    70667195            selectedChangesetStatus.link( changesetStatus ); // Ensure that direct updates to status on server via wp.customizer.previewer.save() will update selection.
     
    79858114            });
    79868115        })();
    7987 
    7988         // Publish settings section and controls.
    7989         api.control( 'changeset_status', 'changeset_scheduled_date', function( statusControl, dateControl ) {
    7990             $.when( statusControl.deferred.embedded, dateControl.deferred.embedded ).done( function() {
    7991                 var radioNodes, statusElement, toggleDateControl, publishWhenTime, pollInterval, updateTimeArrivedPoller, timeArrivedPollingInterval = 1000;
    7992 
    7993                 radioNodes = statusControl.container.find( 'input[type=radio][name]' );
    7994                 statusElement = new api.Element( radioNodes );
    7995                 statusControl.elements.push( statusElement );
    7996 
    7997                 statusElement.sync( api.state( 'selectedChangesetStatus' ) );
    7998                 statusElement.set( api.state( 'selectedChangesetStatus' ).get() );
    7999 
    8000                 dateControl.notifications.alt = true;
    8001                 dateControl.deferred.embedded.done( function() {
    8002                     api.state( 'selectedChangesetDate' ).sync( dateControl.setting );
    8003                     api.state( 'selectedChangesetDate' ).set( dateControl.setting() );
    8004                 } );
    8005 
    8006                 publishWhenTime = function() {
    8007                     api.state( 'selectedChangesetStatus' ).set( 'publish' );
    8008                     api.previewer.save();
    8009                 };
    8010 
    8011                 // Start countdown for when the dateTime arrives, or clear interval when it is .
    8012                 updateTimeArrivedPoller = function() {
    8013                     var shouldPoll = (
    8014                         'future' === api.state( 'changesetStatus' ).get() &&
    8015                         'future' === api.state( 'selectedChangesetStatus' ).get() &&
    8016                         api.state( 'changesetDate' ).get() &&
    8017                         api.state( 'selectedChangesetDate' ).get() === api.state( 'changesetDate' ).get() &&
    8018                         api.utils.getRemainingTime( api.state( 'changesetDate' ).get() ) >= 0
    8019                     );
    8020 
    8021                     if ( shouldPoll && ! pollInterval ) {
    8022                         pollInterval = setInterval( function() {
    8023                             var remainingTime = api.utils.getRemainingTime( api.state( 'changesetDate' ).get() );
    8024                             api.state( 'remainingTimeToPublish' ).set( remainingTime );
    8025                             if ( remainingTime <= 0 ) {
    8026                                 clearInterval( pollInterval );
    8027                                 pollInterval = 0;
    8028                                 publishWhenTime();
    8029                             }
    8030                         }, timeArrivedPollingInterval );
    8031                     } else if ( ! shouldPoll && pollInterval ) {
    8032                         clearInterval( pollInterval );
    8033                         pollInterval = 0;
    8034                     }
    8035                 };
    8036 
    8037                 api.state( 'changesetDate' ).bind( updateTimeArrivedPoller );
    8038                 api.state( 'selectedChangesetDate' ).bind( updateTimeArrivedPoller );
    8039                 api.state( 'changesetStatus' ).bind( updateTimeArrivedPoller );
    8040                 api.state( 'selectedChangesetStatus' ).bind( updateTimeArrivedPoller );
    8041                 updateTimeArrivedPoller();
    8042 
    8043                 // Ensure dateControl only appears when selected status is future.
    8044                 dateControl.active.validate = function() {
    8045                     return 'future' === statusElement.get();
    8046                 };
    8047                 toggleDateControl = function( value ) {
    8048                     dateControl.active.set( 'future' === value );
    8049                 };
    8050                 toggleDateControl( statusElement.get() );
    8051                 statusElement.bind( toggleDateControl );
    8052 
    8053                 // Show notification on date control when status is future but it isn't a future date.
    8054                 api.state( 'saving' ).bind( function( isSaving ) {
    8055                     if ( isSaving && 'future' === api.state( 'selectedChangesetStatus' ).get() ) {
    8056                         dateControl.toggleFutureDateNotification( ! dateControl.isFutureDate() );
    8057                     }
    8058                 } );
    8059             } );
    8060         } );
    80618116
    80628117        // Toggle visibility of Header Video notice when active state change.
  • trunk/src/wp-includes/class-wp-customize-control.php

    r41740 r41750  
    431431     *
    432432     * @since 3.4.0
     433     * @since 4.9.0 Return a `data-customize-setting-key-link` attribute if a setting is not registered for the supplied setting key.
    433434     *
    434435     * @param string $setting_key
    435      * @return string Data link parameter, if $setting_key is a valid setting, empty string otherwise.
     436     * @return string Data link parameter, a `data-customize-setting-link` attribute if the `$setting_key` refers to a pre-registered setting,
     437     *                and a `data-customize-setting-key-link` attribute if the setting is not yet registered.
    436438     */
    437439    public function get_link( $setting_key = 'default' ) {
    438         if ( ! isset( $this->settings[ $setting_key ] ) )
    439             return '';
    440 
    441         return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"';
     440        if ( isset( $this->settings[ $setting_key ] ) && $this->settings[ $setting_key ] instanceof WP_Customize_Setting ) {
     441            return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"';
     442        } else {
     443            return 'data-customize-setting-key-link="' . esc_attr( $setting_key ) . '"';
     444        }
    442445    }
    443446
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r41749 r41750  
    36433643            <button type="button" class="button-link button-link-delete"><?php _e( 'Discard changes' ); ?></button>
    36443644        </script>
     3645        <script type="text/html" id="tmpl-customize-selected-changeset-status-control">
     3646            <# var inputId = _.uniqueId( 'customize-selected-changeset-status-control-input-' ); #>
     3647            <# var descriptionId = _.uniqueId( 'customize-selected-changeset-status-control-description-' ); #>
     3648            <# if ( data.label ) { #>
     3649                <label for="{{ inputId }}" class="customize-control-title">{{ data.label }}</label>
     3650            <# } #>
     3651            <# if ( data.description ) { #>
     3652                <span id="{{ descriptionId }}" class="description customize-control-description">{{{ data.description }}}</span>
     3653            <# } #>
     3654            <# _.each( data.choices, function( choice ) { #>
     3655                <# var choiceId = inputId + '-' + choice.status; #>
     3656                <span class="customize-inside-control-row">
     3657                    <input id="{{ choiceId }}" type="radio" value="{{ choice.status }}" name="{{ inputId }}" data-customize-setting-key-link="default">
     3658                    <label for="{{ choiceId }}">{{ choice.label }}</label>
     3659                </span>
     3660            <# } ); #>
     3661        </script>
    36453662        <?php
    36463663    }
     
    40254042        }
    40264043
     4044        $current_user_can_publish = current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts );
     4045
     4046        // @todo Include all of the status labels here from script-loader.php, and then allow it to be filtered.
     4047        $status_choices = array();
     4048        if ( $current_user_can_publish ) {
     4049            $status_choices[] = array(
     4050                'status' => 'publish',
     4051                'label' => __( 'Publish' ),
     4052            );
     4053        }
     4054        $status_choices[] = array(
     4055            'status' => 'draft',
     4056            'label' => __( 'Save Draft' ),
     4057        );
     4058        if ( $current_user_can_publish ) {
     4059            $status_choices[] = array(
     4060                'status' => 'future',
     4061                'label' => __( 'Schedule' ),
     4062            );
     4063        }
     4064
    40274065        // Prepare Customizer settings to pass to JavaScript.
    40284066        $changeset_post = null;
    40294067        if ( $changeset_post_id ) {
    40304068            $changeset_post = get_post( $changeset_post_id );
     4069        }
     4070
     4071        if ( $this->changeset_post_id() && 'future' === get_post_status( $this->changeset_post_id() ) ) {
     4072            $initial_date = get_the_time( 'Y-m-d H:i:s', $this->changeset_post_id() );
     4073        } else {
     4074            $initial_date = current_time( 'mysql', false );
    40314075        }
    40324076
     
    40394083                'latestAutoDraftUuid' => $autosave_autodraft_post ? $autosave_autodraft_post->post_name : null,
    40404084                'status' => $changeset_post ? $changeset_post->post_status : '',
    4041                 'currentUserCanPublish' => current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ),
    4042                 'publishDate' => $changeset_post ? $changeset_post->post_date : '', // @todo Only if future status? Rename to just date?
     4085                'currentUserCanPublish' => $current_user_can_publish,
     4086                'publishDate' => $initial_date,
     4087                'statusChoices' => $status_choices,
    40434088            ),
    40444089            'initialServerDate' => current_time( 'mysql', false ),
     4090            'dateFormat' => get_option( 'date_format' ),
     4091            'timeFormat' => get_option( 'time_format' ),
    40454092            'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
    40464093            'initialClientTimestamp' => -1, // To be set with JS below.
     
    42064253        /* Publish Settings */
    42074254
     4255        // Note the controls for this section are added via JS.
    42084256        $this->add_section( 'publish_settings', array(
    42094257            'title' => __( 'Publish Settings' ),
     
    42134261            'active_callback' => array( $this, 'is_theme_active' ),
    42144262        ) );
    4215 
    4216         /* Publish Settings Controls */
    4217         $status_choices = array(
    4218             'publish' => __( 'Publish' ),
    4219             'draft' => __( 'Save Draft' ),
    4220             'future' => __( 'Schedule' ),
    4221         );
    4222 
    4223         if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
    4224             unset( $status_choices['publish'] );
    4225         }
    4226 
    4227         $this->add_control( 'changeset_status', array(
    4228             'section' => 'publish_settings',
    4229             'priority' => 10,
    4230             'settings' => array(),
    4231             'type' => 'radio',
    4232             'label' => __( 'Action' ),
    4233             'choices' => $status_choices,
    4234             'capability' => 'customize',
    4235         ) );
    4236 
    4237         if ( $this->changeset_post_id() && 'future' === get_post_status( $this->changeset_post_id() ) ) {
    4238             $initial_date = get_the_time( 'Y-m-d H:i:s', $this->changeset_post_id() );
    4239         } else {
    4240             $initial_date = current_time( 'mysql', false );
    4241         }
    4242 
    4243         $this->add_control( new WP_Customize_Date_Time_Control( $this, 'changeset_scheduled_date', array(
    4244             'section' => 'publish_settings',
    4245             'priority' => 20,
    4246             'settings' => array(),
    4247             'type' => 'date_time',
    4248             'min_year' => date( 'Y' ),
    4249             'allow_past_date' => false,
    4250             'include_time' => true,
    4251             'twelve_hour_format' => false !== stripos( get_option( 'time_format' ), 'a' ),
    4252             'description' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ),
    4253             'capability' => 'customize',
    4254             'default_value' => $initial_date,
    4255         ) ) );
    42564263
    42574264        /* Themes (controls are loaded via ajax) */
  • trunk/src/wp-includes/customize/class-wp-customize-date-time-control.php

    r41672 r41750  
    6767
    6868    /**
    69      * Default date/time to be displayed in the control.
    70      *
    71      * @since 4.9.0
    72      * @var string
    73      */
    74     public $default_value;
    75 
    76     /**
    7769     * Don't render the control's content - it's rendered with a JS template.
    7870     *
     
    9587        $data['twelveHourFormat'] = (bool) $this->twelve_hour_format;
    9688        $data['includeTime'] = (bool) $this->include_time;
    97         $data['defaultValue'] = $this->default_value;
    9889
    9990        return $data;
  • trunk/src/wp-includes/script-loader.php

    r41721 r41750  
    567567        'cancel'             => __( 'Cancel' ),
    568568        'close'              => __( 'Close' ),
     569        'action'             => __( 'Action' ),
    569570        'cheatin'            => __( 'Cheatin&#8217; uh?' ),
    570571        'notAllowed'         => __( 'Sorry, you are not allowed to customize this site.' ),
     
    595596            array( 'singular', 'plural' )
    596597        ),
     598        'scheduleDescription' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ),
    597599    ) );
    598600    $scripts->add( 'customize-selective-refresh', "/wp-includes/js/customize-selective-refresh$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 );
  • trunk/tests/phpunit/tests/customize/manager.php

    r41720 r41750  
    25822582        $this->assertNotEmpty( $data );
    25832583
    2584         $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'changeset', 'timeouts', 'initialClientTimestamp', 'initialServerDate', 'initialServerTimestamp', 'l10n' ), array_keys( $data ) );
     2584        $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'changeset', 'timeouts', 'dateFormat', 'timeFormat', 'initialClientTimestamp', 'initialServerDate', 'initialServerTimestamp', 'l10n' ), array_keys( $data ) );
    25852585        $this->assertEquals( $autofocus, $data['autofocus'] );
    25862586        $this->assertArrayHasKey( 'save', $data['nonce'] );
     
    25972597                'currentUserCanPublish',
    25982598                'publishDate',
     2599                'statusChoices',
    25992600            ),
    26002601            array_keys( $data['changeset'] )
  • trunk/tests/qunit/wp-admin/js/customize-controls.js

    r41726 r41750  
    711711                section: section.id,
    712712                type: 'date_time',
     713                setting: new wp.customize.Value( datetime ),
    713714                includeTime: true,
    714                 content: '<li id="customize-control-' + controlId + '" class="customize-control"></li>',
    715                 defaultValue: datetime
     715                content: '<li id="customize-control-' + controlId + '" class="customize-control"></li>'
    716716            }
    717717        } );
Note: See TracChangeset for help on using the changeset viewer.