diff --git a/.travis.yml b/.travis.yml
index 003dcbac..1dbd3883 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,7 @@ env:
- WP_VERSION=latest WP_MULTISITE=1
install:
+ - nvm install 4 && nvm use 4
- export DEV_LIB_PATH=dev-lib
- if [ ! -e "$DEV_LIB_PATH" ] && [ -L .travis.yml ]; then export DEV_LIB_PATH=$( dirname $( readlink .travis.yml ) ); fi
- source $DEV_LIB_PATH/travis.install.sh
diff --git a/css/customize-snapshots.css b/css/customize-snapshots.css
index 53c8ee3a..ddb771d6 100644
--- a/css/customize-snapshots.css
+++ b/css/customize-snapshots.css
@@ -1,10 +1,12 @@
-#snapshot-preview-link, #snapshot-edit-link {
+#snapshot-preview-link,
+#snapshot-schedule-button {
float: right;
margin-top: 13px;
margin-right: 4px;
color: #656a6f;
}
-#snapshot-edit-link{
+
+#snapshot-schedule-button {
display: block;
}
@@ -13,11 +15,13 @@
#snapshot-preview-link:active {
color: #191e23;
}
+
#snapshot-save {
float: right;
margin-top: 9px;
margin-right: 9px;
}
+
#customize-header-actions:not(.button-added) .button#save {
visibility: hidden;
}
@@ -53,4 +57,107 @@
margin-top: 6px;
margin-right: 6px;
}
-}
\ No newline at end of file
+}
+
+#snapshot-schedule {
+ background: #fff !important;
+ border-bottom: 1px solid #ddd;
+ line-height: 1.5;
+ left: 0;
+ top: 46px;
+ position: absolute;
+ width: 100%;
+ box-shadow: 0 5px 0 0 rgba(0,0,0,0.05);
+}
+
+#snapshot-schedule .snapshot-schedule-title {
+ color: #555;
+ padding: 10px 10px 0;
+}
+
+#snapshot-schedule .snapshot-schedule-title h3 {
+ margin: .2em 2em .75em 0;
+}
+
+#snapshot-schedule a.snapshot-edit-link {
+ position: absolute;
+ top: 4px;
+ right: 1px;
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ -webkit-appearance: none;
+ background: transparent;
+ color: #555;
+ border: none;
+ padding: 10px;
+}
+
+#snapshot-schedule a.snapshot-edit-link:focus,
+#snapshot-schedule a.snapshot-edit-link:hover {
+ color: #0073aa;
+
+}
+
+#snapshot-schedule a.snapshot-edit-link:before {
+ padding: 4px;
+ position: absolute;
+ top: 5px;
+ left: 6px;
+ -webkit-border-radius: 100%;
+ border-radius: 100%;
+}
+
+#snapshot-schedule a.snapshot-edit-link:focus:before {
+ -webkit-box-shadow:
+ 0 0 0 1px #5b9dd9,
+ 0 0 2px 1px rgba(30, 140, 190, .8);
+ box-shadow:
+ 0 0 0 1px #5b9dd9,
+ 0 0 2px 1px rgba(30, 140, 190, .8);
+}
+
+#snapshot-schedule .snapshot-schedule-control {
+ padding: 10px;
+}
+
+#snapshot-schedule .accordion-section-title {
+ padding: 10px;
+}
+
+#snapshot-schedule .reset-time {
+ font-weight: normal;
+ font-size: 80%;
+ display: none;
+}
+
+.snapshot-schedule-control select.date-input {
+ height: 28px;
+}
+
+.snapshot-schedule-control select,
+.snapshot-schedule-control input.date-input {
+ min-width: 10%;
+ width: auto;
+}
+
+.snapshot-schedule-control input.date-input {
+ -moz-appearance: textfield;
+}
+
+.snapshot-schedule-control input.date-input::-webkit-outer-spin-button,
+.snapshot-schedule-control input.date-input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+.wp-full-overlay .wp-full-overlay-sidebar .wp-full-overlay-header {
+ padding-left: 15px;
+ z-index: 500101;
+}
+
+.select2-container {
+ z-index: 500100 !important;
+}
diff --git a/js/customize-snapshots.js b/js/customize-snapshots.js
index 946b2430..3934d407 100644
--- a/js/customize-snapshots.js
+++ b/js/customize-snapshots.js
@@ -1,5 +1,4 @@
/* global jQuery, _customizeSnapshots */
-/* eslint-disable no-extra-parens */
( function( api, $ ) {
'use strict';
@@ -12,7 +11,21 @@
component = api.Snapshots;
- component.data = {};
+ component.schedule = {};
+
+ component.data = {
+ action: '',
+ uuid: '',
+ editLink: '',
+ publishDate: '',
+ postStatus: '',
+ currentUserCanPublish: '',
+ initialServerDate: '',
+ initialServerTimestamp: 0,
+ initialClientTimestamp: 0,
+ i18n: {},
+ dirty: false
+ };
if ( 'undefined' !== typeof _customizeSnapshots ) {
_.extend( component.data, _customizeSnapshots );
@@ -27,6 +40,9 @@
window._wpCustomizeControlsL10n.save = component.data.i18n.publish;
window._wpCustomizeControlsL10n.saved = component.data.i18n.published;
+ // Set the initial client timestamp.
+ component.data.initialClientTimestamp = component.dateValueOf();
+
api.bind( 'ready', function() {
api.state.create( 'snapshot-exists', component.data.snapshotExists );
api.state.create( 'snapshot-saved', true );
@@ -40,10 +56,20 @@
component.extendPreviewerQuery();
component.addButtons();
+ component.addSchedule();
$( '#snapshot-save' ).on( 'click', function( event ) {
+ var scheduleDate;
event.preventDefault();
- component.sendUpdateSnapshotRequest( { status: 'draft' } );
+ if ( ! _.isEmpty( component.schedule.template ) && component.isFutureDate() ) {
+ scheduleDate = component.getDateFromInputs();
+ component.sendUpdateSnapshotRequest( {
+ status: 'future',
+ publish_date: component.formatDate( scheduleDate )
+ } );
+ } else {
+ component.sendUpdateSnapshotRequest( { status: 'draft' } );
+ }
} );
$( '#snapshot-submit' ).on( 'click', function( event ) {
event.preventDefault();
@@ -159,13 +185,21 @@
component.addButtons = function() {
var header = $( '#customize-header-actions' ),
publishButton = header.find( '#save' ),
- snapshotEditLinkTemplate = wp.template( 'snapshot-edit-link' ),
- snapshotButton, submitButton, data, setPreviewLinkHref, snapshotEditLinkEl;
+ snapshotButton, scheduleButton, submitButton, data, setPreviewLinkHref, snapshotButtonText;
// Save/update button.
snapshotButton = wp.template( 'snapshot-save' );
+ if ( api.state( 'snapshot-exists' ).get() ) {
+ if ( 'future' === component.data.postStatus ) {
+ snapshotButtonText = component.data.i18n.scheduleButton;
+ } else {
+ snapshotButtonText = component.data.i18n.updateButton;
+ }
+ } else {
+ snapshotButtonText = component.data.i18n.saveButton;
+ }
data = {
- buttonText: api.state( 'snapshot-exists' ).get() ? component.data.i18n.updateButton : component.data.i18n.saveButton
+ buttonText: snapshotButtonText
};
snapshotButton = $( $.trim( snapshotButton( data ) ) );
if ( ! component.data.currentUserCanPublish ) {
@@ -174,20 +208,25 @@
snapshotButton.prop( 'disabled', true );
snapshotButton.insertAfter( publishButton );
- snapshotEditLinkEl = $( $.trim( snapshotEditLinkTemplate( component.data ) ) );
- snapshotEditLinkEl.insertAfter( snapshotButton );
+ // Schedule button.
+ scheduleButton = wp.template( 'snapshot-schedule-button' );
+ scheduleButton = $( $.trim( scheduleButton( {} ) ) );
+ scheduleButton.insertAfter( snapshotButton );
+
if ( ! component.data.editLink ) {
- snapshotEditLinkEl.hide();
+ scheduleButton.hide();
}
- api.state.bind( 'change', function() {
- snapshotEditLinkEl.toggle( api.state( 'snapshot-saved' ).get() && api.state( 'snapshot-exists' ).get() );
+
+ api.state( 'change', function() {
+ scheduleButton.toggle( api.state( 'snapshot-saved' ).get() && api.state( 'snapshot-exists' ).get() );
+ } );
+
+ api.state( 'snapshot-exists' ).bind( function( exist ) {
+ scheduleButton.toggle( exist );
} );
api.state( 'snapshot-saved' ).bind( function( saved ) {
snapshotButton.prop( 'disabled', saved );
- if ( saved ) {
- snapshotEditLinkEl.attr( 'href', component.data.editLink );
- }
} );
api.state( 'saved' ).bind( function( saved ) {
@@ -204,9 +243,6 @@
if ( exists ) {
buttonText = component.data.i18n.updateButton;
permsMsg = component.data.i18n.permsMsg.update;
- if ( component.data.editLink ) {
- snapshotEditLinkEl.attr( 'href', component.data.editLink );
- }
} else {
buttonText = component.data.i18n.saveButton;
permsMsg = component.data.i18n.permsMsg.save;
@@ -255,6 +291,158 @@
header.addClass( 'button-added' );
};
+ /**
+ * Renders snapshot schedule and handles it's events.
+ *
+ * @returns {void}
+ */
+ component.addSchedule = function addSchedule() {
+ var sliceBegin = 0,
+ sliceEnd = -2;
+
+ // Inject the UI.
+ if ( _.isEmpty( component.schedule.template ) ) {
+ if ( '0000-00-00 00:00:00' === component.data.publishDate ) {
+ component.data.publishDate = component.getCurrentTime();
+ }
+
+ // Normalize date with secs set as zeros removed.
+ component.data.publishDate = component.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
+
+ // Extend the components data object and add the parsed datetime strings.
+ component.data = _.extend( component.data, component.parseDateTime( component.data.publishDate ) );
+
+ // Add the template to the DOM.
+ component.schedule.template = $( $.trim( wp.template( 'snapshot-schedule' )( component.data ) ) );
+ component.schedule.template.hide().appendTo( $( '#customize-header-actions' ) );
+
+ // Store the date inputs.
+ component.schedule.inputs = component.schedule.template.find( '.date-input' );
+
+ component.schedule.inputs.on( 'input', function() {
+ component.populateSetting();
+ } );
+
+ component.schedule.inputs.on( 'blur', function() {
+ component.populateInputs();
+ component.populateSetting();
+ } );
+
+ component.updateCountdown();
+
+ component.schedule.template.find( '.reset-time a' ).on( 'click', function( event ) {
+ event.preventDefault();
+ component.updateSchedule();
+ } );
+ }
+
+ // Listen for click events.
+ $( '#snapshot-schedule-button' ).on( 'click', function( event ) {
+ event.preventDefault();
+ component.schedule.template.toggle();
+ } );
+
+ api.state( 'snapshot-saved' ).bind( function( saved ) {
+ if ( saved ) {
+ component.updateSchedule();
+ }
+ } );
+
+ api.bind( 'change', function() {
+ component.data.dirty = true;
+ component.schedule.template.find( 'a.snapshot-edit-link' ).hide();
+ } );
+
+ api.state( 'saved' ).bind( function( saved ) {
+ if ( saved && ! _.isEmpty( component.schedule.template ) ) {
+ component.data.publishDate = component.getCurrentTime();
+ component.updateSchedule();
+ component.schedule.template.hide();
+ component.data.dirty = false;
+ }
+ } );
+
+ api.state( 'snapshot-exists' ).bind( function( exists ) {
+ if ( exists && ! _.isEmpty( component.schedule.template ) ) {
+ component.updateSchedule();
+ } else {
+ component.schedule.template.hide();
+ }
+ } );
+ };
+
+ /**
+ * Updates snapshot schedule with `component.data`.
+ *
+ * @return {void}
+ */
+ component.updateSchedule = function updateSchedule() {
+ var parsed,
+ sliceBegin = 0,
+ sliceEnd = -2;
+
+ if ( _.isEmpty( component.schedule.template ) ) {
+ return;
+ }
+
+ if ( '0000-00-00 00:00:00' === component.data.publishDate ) {
+ component.data.publishDate = component.getCurrentTime();
+ }
+
+ // Normalize date with seconds removed.
+ component.data.publishDate = component.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
+
+ // Update date controls.
+ component.schedule.template.find( 'a.snapshot-edit-link' )
+ .attr( 'href', component.data.editLink )
+ .show();
+ parsed = component.parseDateTime( component.data.publishDate );
+
+ component.schedule.inputs.each( function() {
+ var input = $( this ),
+ fieldName = input.data( 'date-input' );
+
+ $( this ).val( parsed[fieldName] );
+ } );
+
+ component.populateSetting();
+ };
+
+ /**
+ * Update the scheduled countdown text.
+ *
+ * Hides countdown if post_status is not already future.
+ * Toggles the countdown if there is no remaining time.
+ *
+ * @returns {boolean} True if date inputs are valid.
+ */
+ component.updateCountdown = function updateCountdown() {
+ var countdown = component.schedule.template.find( '.snapshot-scheduled-countdown' ),
+ countdownTemplate = wp.template( 'snapshot-scheduled-countdown' ),
+ dateTimeFromInput = component.getDateFromInputs(),
+ millisecondsDivider = 1000,
+ remainingTime;
+
+ if ( ! dateTimeFromInput ) {
+ return false;
+ }
+
+ remainingTime = dateTimeFromInput.valueOf();
+ remainingTime -= component.dateValueOf( component.getCurrentTime() );
+ remainingTime = Math.ceil( remainingTime / millisecondsDivider );
+
+ if ( 0 < remainingTime ) {
+ countdown.text( countdownTemplate( {
+ remainingTime: remainingTime
+ } ) );
+ countdown.show();
+ } else {
+ countdown.hide();
+ }
+
+ return true;
+ };
+
/**
* Silently update the saved state to be true without triggering the
* changed event so that the AYS beforeunload dialog won't appear
@@ -281,22 +469,17 @@
*/
component.sendUpdateSnapshotRequest = function( options ) {
var spinner = $( '#customize-header-actions .spinner' ),
- request, data, args;
+ request, data;
- args = _.extend(
+ data = _.extend(
{
status: 'draft'
},
- options
- );
-
- data = _.extend(
- {},
api.previewer.query(),
+ options,
{
nonce: api.settings.nonce.snapshot,
- customize_snapshot_uuid: component.data.uuid,
- status: args.status
+ customize_snapshot_uuid: component.data.uuid
}
);
request = wp.ajax.post( 'customize_update_snapshot', data );
@@ -307,6 +490,11 @@
if ( response.edit_link ) {
component.data.editLink = response.edit_link;
}
+ if ( response.snapshot_publish_date ) {
+ component.data.publishDate = response.snapshot_publish_date;
+ }
+ component.updateSchedule();
+ component.data.dirty = false;
// @todo Remove privateness from _handleSettingValidities in Core.
if ( api._handleSettingValidities && response.setting_validities ) {
@@ -320,9 +508,10 @@
request.done( function() {
var url = api.previewer.previewUrl(),
regex = new RegExp( '([?&])customize_snapshot_uuid=.*?(&|$)', 'i' ),
- separator = url.indexOf( '?' ) !== -1 ? '&' : '?',
+ notFound = -1,
+ separator = url.indexOf( '?' ) !== notFound ? '&' : '?',
customizeUrl = window.location.href,
- customizeSeparator = customizeUrl.indexOf( '?' ) !== -1 ? '&' : '?';
+ customizeSeparator = customizeUrl.indexOf( '?' ) !== notFound ? '&' : '?';
if ( url.match( regex ) ) {
url = url.replace( regex, '$1customize_snapshot_uuid=' + encodeURIComponent( component.data.uuid ) + '$2' );
@@ -340,7 +529,7 @@
}
api.state( 'snapshot-saved' ).set( true );
- if ( 'pending' === args.status ) {
+ if ( 'pending' === data.status ) {
api.state( 'snapshot-submitted' ).set( true );
}
component.resetSavedStateQuietly();
@@ -399,6 +588,209 @@
} );
};
+ /**
+ * Get date from inputs.
+ *
+ * @returns {Date|null} Date created from inputs or null if invalid date.
+ */
+ component.getDateFromInputs = function getDateFromInputs() {
+ var template = component.schedule.template,
+ monthOffset = 1,
+ date;
+
+ date = new Date(
+ parseInt( template.find( '[data-date-input="year"]' ).val(), 10 ),
+ parseInt( template.find( '[data-date-input="month"]' ).val(), 10 ) - monthOffset,
+ parseInt( template.find( '[data-date-input="day"]' ).val(), 10 ),
+ parseInt( template.find( '[data-date-input="hour"]' ).val(), 10 ),
+ parseInt( template.find( '[data-date-input="minute"]' ).val(), 10 )
+ );
+
+ if ( isNaN( date.valueOf() ) ) {
+ return null;
+ }
+
+ date.setSeconds( 0 );
+
+ return date;
+ };
+
+ /**
+ * Parse datetime string.
+ *
+ * @param {string} datetime Date/Time string.
+ * @returns {object|null} Returns object containing date components or null if parse error.
+ */
+ component.parseDateTime = function parseDateTime( datetime ) {
+ var matches = datetime.match( /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/ );
+
+ if ( ! matches ) {
+ return null;
+ }
+
+ matches.shift();
+
+ return {
+ year: matches.shift(),
+ month: matches.shift(),
+ day: matches.shift(),
+ hour: matches.shift(),
+ minute: matches.shift(),
+ second: matches.shift()
+ };
+ };
+
+ /**
+ * Format a Date Object. Returns 'Y-m-d H:i:s' format.
+ *
+ * @props http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript#comment33639551_10073699
+ *
+ * @param {Date} date A Date object.
+ * @returns {string} A formatted date String.
+ */
+ component.formatDate = function formatDate( date ) {
+ var formattedDate,
+ yearLength = 4,
+ nonYearLength = 2,
+ monthOffset = 1;
+
+ formattedDate = ( '0000' + date.getFullYear() ).substr( -yearLength, yearLength );
+ formattedDate += '-' + ( '00' + ( date.getMonth() + monthOffset ) ).substr( -nonYearLength, nonYearLength );
+ formattedDate += '-' + ( '00' + date.getDate() ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ' ' + ( '00' + date.getHours() ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ':' + ( '00' + date.getMinutes() ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ':' + ( '00' + date.getSeconds() ).substr( -nonYearLength, nonYearLength );
+
+ return formattedDate;
+ };
+
+ /**
+ * Populate inputs from the setting value, if none of them are currently focused.
+ *
+ * @returns {boolean} Whether the inputs were populated.
+ */
+ component.populateInputs = function populateInputs() {
+ var parsed;
+
+ if ( component.schedule.inputs.is( ':focus' ) || '0000-00-00 00:00:00' === component.data.publishDate ) {
+ return false;
+ }
+
+ parsed = component.parseDateTime( component.data.publishDate );
+ if ( ! parsed ) {
+ return false;
+ }
+
+ component.schedule.inputs.each( function() {
+ var input = $( this ),
+ fieldName = input.data( 'date-input' );
+
+ if ( ! $( this ).is( 'select' ) && '' === $( this ).val() ) {
+ $( this ).val( parsed[fieldName] );
+ }
+ } );
+ return true;
+ };
+
+ /**
+ * Populate setting value from the inputs.
+ *
+ * @returns {boolean} Whether the date inputs currently represent a valid date.
+ */
+ component.populateSetting = function populateSetting() {
+ var date = component.getDateFromInputs(),
+ save = $( '#snapshot-save' ),
+ scheduled;
+
+ if ( ! date ) {
+ return false;
+ }
+
+ date.setSeconds( 0 );
+ scheduled = component.formatDate( date ) !== component.data.publishDate;
+
+ if ( save.length ) {
+
+ // Change update button to schedule.
+ if ( component.isFutureDate() ) {
+ save.html( component.data.i18n.scheduleButton );
+ } else {
+ save.html( component.data.i18n.updateButton );
+ }
+
+ if ( scheduled || component.data.dirty ) {
+ save.prop( 'disabled', false );
+ } else {
+ save.prop( 'disabled', true );
+ }
+ }
+
+ component.updateCountdown();
+ component.schedule.template.find( '.reset-time' ).toggle( scheduled );
+
+ return true;
+ };
+
+ /**
+ * Check if the schedule date is in the future.
+ *
+ * @returns {boolean} True if future date.
+ */
+ component.isFutureDate = function isFutureDate() {
+ var date = component.getDateFromInputs(),
+ millisecondsDivider = 1000,
+ remainingTime;
+
+ if ( ! date ) {
+ return false;
+ }
+
+ remainingTime = component.dateValueOf( date );
+ remainingTime -= component.dateValueOf( component.getCurrentTime() );
+ remainingTime = Math.ceil( remainingTime / millisecondsDivider );
+
+ return 0 < remainingTime;
+ };
+
+ /**
+ * Get current date/time in the site's timezone.
+ *
+ * Same functionality as the `current_time( 'mysql', false )` function in PHP.
+ *
+ * @returns {string} Current datetime string.
+ */
+ component.getCurrentTime = function getCurrentTime() {
+ var currentDate = new Date( component.data.initialServerDate ),
+ currentTimestamp = component.dateValueOf(),
+ timestampDifferential;
+
+ timestampDifferential = currentTimestamp - component.data.initialClientTimestamp;
+ timestampDifferential += component.data.initialClientTimestamp - component.data.initialServerTimestamp;
+ currentDate.setTime( currentDate.getTime() + timestampDifferential );
+
+ return component.formatDate( currentDate );
+ };
+
+ /**
+ * Get the primitive value of a Date object.
+ *
+ * @param {string|Date} dateString The post status for the snapshot.
+ * @returns {object|string} The primitive value or date object.
+ */
+ component.dateValueOf = function( dateString ) {
+ var date;
+
+ if ( 'string' === typeof dateString ) {
+ date = new Date( dateString );
+ } else if ( dateString instanceof Date ) {
+ date = dateString;
+ } else {
+ date = new Date();
+ }
+
+ return date.valueOf();
+ };
+
component.init();
} )( wp.customize, jQuery );
diff --git a/package.json b/package.json
index 3ad081a1..086a2aa9 100644
--- a/package.json
+++ b/package.json
@@ -1,22 +1,23 @@
{
- "name": "customize-snapshots",
- "title": "Customize Snapshots",
- "homepage": "https://github.com/xwp/wp-customize-snapshots",
- "repository": {
- "type": "git",
- "url": "https://github.com/xwp/wp-customize-snapshots.git"
- },
- "author": "XWP",
- "license": "GPL-2.0+",
- "devDependencies": {
- "grunt": "~0.4.5",
- "grunt-checktextdomain": "~1.0.0",
- "grunt-contrib-clean": "~1.0.0",
- "grunt-contrib-copy": "~1.0.0",
- "grunt-contrib-cssmin": "~1.0.1",
- "grunt-contrib-jshint": "~1.0.0",
- "grunt-contrib-uglify": "~1.0.1",
- "grunt-shell": "~1.3.0",
- "grunt-wp-deploy": "^1.1.0"
- }
+ "name": "customize-snapshots",
+ "title": "Customize Snapshots",
+ "homepage": "https://github.com/xwp/wp-customize-snapshots",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/xwp/wp-customize-snapshots.git"
+ },
+ "author": "XWP",
+ "license": "GPL-2.0+",
+ "devDependencies": {
+ "eslint": "^3.2.2",
+ "grunt": "~0.4.5",
+ "grunt-checktextdomain": "~1.0.0",
+ "grunt-contrib-clean": "~1.0.0",
+ "grunt-contrib-copy": "~1.0.0",
+ "grunt-contrib-cssmin": "~1.0.1",
+ "grunt-contrib-jshint": "~1.0.0",
+ "grunt-contrib-uglify": "~1.0.1",
+ "grunt-shell": "~1.3.0",
+ "grunt-wp-deploy": "^1.1.0"
+ }
}
diff --git a/php/class-customize-snapshot-manager.php b/php/class-customize-snapshot-manager.php
index 62d83872..d02b4369 100644
--- a/php/class-customize-snapshot-manager.php
+++ b/php/class-customize-snapshot-manager.php
@@ -525,6 +525,17 @@ public function preview_early_nav_menus_in_customizer() {
);
if ( $is_nav_menu_setting ) {
$setting->preview();
+
+ /*
+ * The following is redundant because it will be done later in
+ * Customize_Snapshot_Manager::preview_snapshot_settings().
+ * Also note that the $setting instance here will likely be
+ * blown away inside of WP_Customize_Nav_Menus::customize_register(),
+ * when add_setting is called there. What matters here is that
+ * preview() is called on the setting _before_ the logic inside
+ * WP_Customize_Nav_Menus::customize_register() runs, so that
+ * the nav menu sections will be created.
+ */
$setting->dirty = true;
}
}
@@ -634,16 +645,25 @@ public function enqueue_controls_scripts() {
wp_enqueue_style( 'customize-snapshots' );
wp_enqueue_script( 'customize-snapshots' );
+ if ( $this->snapshot ) {
+ $post = $this->snapshot->post();
+ $this->override_post_date_default_data( $post );
+ }
// Script data array.
$exports = apply_filters( 'customize_snapshots_export_data', array(
'action' => self::AJAX_ACTION,
'uuid' => $this->snapshot ? $this->snapshot->uuid() : self::generate_uuid(),
- 'editLink' => $this->snapshot ? get_edit_post_link( $this->snapshot->post(), 'raw' ) : '',
+ 'editLink' => isset( $post ) ? get_edit_post_link( $post, 'raw' ) : '',
+ 'publishDate' => isset( $post->post_date ) ? $post->post_date : '',
+ 'postStatus' => isset( $post->post_status ) ? $post->post_status : '',
'currentUserCanPublish' => current_user_can( 'customize_publish' ),
+ 'initialServerDate' => current_time( 'mysql', false ),
+ 'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
'i18n' => array(
'saveButton' => __( 'Save', 'customize-snapshots' ),
'updateButton' => __( 'Update', 'customize-snapshots' ),
+ 'scheduleButton' => __( 'Schedule', 'customize-snapshots' ),
'submit' => __( 'Submit', 'customize-snapshots' ),
'submitted' => __( 'Submitted', 'customize-snapshots' ),
'publish' => __( 'Publish', 'customize-snapshots' ),
@@ -780,9 +800,18 @@ function( $value ) {
}
if ( ! $this->snapshot->post() || 'publish' !== $this->snapshot->post()->post_status ) {
- $r = $this->snapshot->save( array(
+ $args = array(
'status' => 'publish',
- ) );
+ );
+
+ // Ensure a scheduled Snapshot is published.
+ if ( $this->snapshot->post() && 'future' === $this->snapshot->post()->post_status ) {
+ $args['edit_date'] = true;
+ $args['post_date'] = current_time( 'mysql', false );
+ $args['post_date_gmt'] = current_time( 'mysql', true );
+ }
+
+ $r = $this->snapshot->save( $args );
if ( is_wp_error( $r ) ) {
add_filter( 'customize_save_response', function( $response ) use ( $r, $that ) {
$response['snapshot_errors'] = $that->prepare_errors_for_response( $r );
@@ -1044,10 +1073,19 @@ public function handle_update_snapshot_request() {
} else {
$status = 'draft';
}
- if ( ! in_array( $status, array( 'draft', 'pending' ), true ) ) {
+ if ( ! in_array( $status, array( 'draft', 'pending', 'future' ), true ) ) {
status_header( 400 );
wp_send_json_error( 'bad_status' );
}
+ $publish_date = isset( $_POST['publish_date'] ) ? $_POST['publish_date'] : '';
+ if ( 'future' === $status ) {
+ $publish_date_obj = new \DateTime( $publish_date );
+ $current_date = new \DateTime();
+ if ( empty( $publish_date ) || ! $publish_date_obj || $publish_date > $current_date ) {
+ status_header( 400 );
+ wp_send_json_error( 'bad_schedule_time' );
+ }
+ }
// Prevent attempting to modify a "locked" snapshot (a published one).
$post = $this->snapshot->post();
@@ -1093,14 +1131,23 @@ function( $value ) {
$data['errors'] = $this->prepare_errors_for_response( $r['errors'] );
wp_send_json_error( $data );
}
-
- $r = $this->snapshot->save( array(
+ $args = array(
'status' => $status,
- ) );
+ );
+ $args['edit_date'] = current_time( 'mysql' );
+
+ if ( isset( $publish_date_obj ) && 'future' === $status ) {
+ $args['post_date'] = $publish_date_obj->format( 'Y-m-d H:i:s' );
+ $args['post_date_gmt'] = '0000-00-00 00:00:00';
+ } else {
+ $args['post_date_gmt'] = $args['post_date'] = '0000-00-00 00:00:00';
+ }
+ $r = $this->snapshot->save( $args );
$post = $this->snapshot->post();
if ( $post ) {
$data['edit_link'] = get_edit_post_link( $post, 'raw' );
+ $data['snapshot_publish_date'] = $post->post_date;
}
if ( is_wp_error( $r ) ) {
@@ -1322,6 +1369,22 @@ public function remove_all_non_snapshot_admin_bar_links( $wp_admin_bar ) {
* Underscore (JS) templates for dialog windows.
*/
public function render_templates() {
+ $data = $this->get_month_choices();
+
+ $tz_string = get_option( 'timezone_string' );
+ if ( $tz_string ) {
+ $tz = new \DateTimezone( $tz_string );
+ $formatted_gmt_offset = $this->format_gmt_offset( $tz->getOffset( new \DateTime() ) / 3600 );
+ $tz_name = str_replace( '_', ' ', $tz->getName() );
+
+ /* translators: 1: timezone name, 2: gmt offset */
+ $date_control_description = sprintf( __( 'This site\'s dates are in the %1$s timezone (currently UTC%2$s).', 'customize-snapshots' ), $tz_name, $formatted_gmt_offset );
+ } else {
+ $formatted_gmt_offset = $this->format_gmt_offset( get_option( 'gmt_offset' ) );
+
+ /* translators: %s: gmt offset */
+ $date_control_description = sprintf( __( 'Dates are in UTC%s.', 'customize-snapshots' ), $formatted_gmt_offset );
+ }
?>
-
+
+
+
+
get_month_abbrev( $wp_locale->get_month( $i ) );
+
+ /* translators: 1: month number (01, 02, etc.), 2: month abbreviation */
+ $months[ $i ]['text'] = sprintf( __( '%1$s-%2$s', 'customize-snapshots' ), $month_number, $month_text );
+ $months[ $i ]['value'] = $month_number;
+ }
+ return array( 'month_choices' => $months );
+ }
+
+ /**
+ * Override default date values to a post.
+ *
+ * @param \WP_Post $post Post.
+ * @return \WP_Post Object if the post data did not apply.
+ */
+ public function override_post_date_default_data( \WP_Post &$post ) {
+ if ( ! is_array( $post ) ) {
+ // Make sure that empty dates are not used in case of setting invalidity.
+ $empty_date = '0000-00-00 00:00:00';
+ if ( $empty_date === $post->post_date ) {
+ $post->post_date = current_time( 'mysql', false );
+ }
+ if ( $empty_date === $post->post_date_gmt ) {
+ $post->post_date_gmt = current_time( 'mysql', true );
+ }
+ if ( $empty_date === $post->post_modified ) {
+ $post->post_modified = current_time( 'mysql', false );
+ }
+ if ( $empty_date === $post->post_modified_gmt ) {
+ $post->post_modified_gmt = current_time( 'mysql', true );
+ }
+ }
+ return $post;
+ }
}
diff --git a/php/class-post-type.php b/php/class-post-type.php
index ca9af763..fb0782cb 100644
--- a/php/class-post-type.php
+++ b/php/class-post-type.php
@@ -508,6 +508,11 @@ public function save( array $args ) {
),
);
if ( ! empty( $args['status'] ) ) {
+ if ( isset( $args['post_date'], $args['edit_date'], $args['post_date_gmt'] ) ) {
+ $post_arr['post_date'] = $args['post_date'];
+ $post_arr['edit_date'] = $args['edit_date'];
+ $post_arr['post_date_gmt'] = $args['post_date_gmt'];
+ }
if ( ! get_post_status_object( $args['status'] ) ) {
return new \WP_Error( 'bad_status' );
}
diff --git a/tests/php/test-class-ajax-customize-snapshot-manager.php b/tests/php/test-class-ajax-customize-snapshot-manager.php
index 360be871..4b6ac33f 100644
--- a/tests/php/test-class-ajax-customize-snapshot-manager.php
+++ b/tests/php/test-class-ajax-customize-snapshot-manager.php
@@ -276,7 +276,9 @@ function test_ajax_update_snapshot_cap_check( $role, $expected_results ) {
if ( $response['success'] ) {
$this->assertNotEmpty( $response['data']['edit_link'] );
+ $this->assertNotEmpty( $response['data']['snapshot_publish_date'] );
unset( $response['data']['edit_link'] );
+ unset( $response['data']['snapshot_publish_date'] );
}
$this->assertSame( $expected_results, $response );
}
@@ -417,4 +419,48 @@ function make_save_snapshot_ajax_call() {
unset( $e );
}
}
+
+ /**
+ * Testing schedule Snapshot
+ */
+ function test_ajax_update_snapshot_schedule() {
+ unset( $GLOBALS['wp_customize'] );
+ remove_all_actions( 'wp_ajax_' . Customize_Snapshot_Manager::AJAX_ACTION );
+
+ $setting_key = 'anyonecanedit';
+ $tomorrow = date( 'Y-m-d H:i:s', time() + 86400 );
+ $this->set_current_user( 'administrator' );
+ $this->set_input_vars( array(
+ 'action' => Customize_Snapshot_Manager::AJAX_ACTION,
+ 'nonce' => wp_create_nonce( Customize_Snapshot_Manager::AJAX_ACTION ),
+ 'customize_snapshot_uuid' => self::UUID,
+ 'customized' => wp_json_encode( array( $setting_key => 'Hello' ) ),
+ 'status' => 'future',
+ 'publish_date' => $tomorrow, // Tomorrow.
+ ) );
+
+ $this->plugin = new Plugin();
+ $this->plugin->init();
+ $this->add_setting();
+
+ $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
+ $post_id = get_plugin_instance()->customize_snapshot_manager->post_type->find_post( self::UUID );
+ $expected_results = array(
+ 'success' => true,
+ 'data' => array(
+ 'errors' => null,
+ 'setting_validities' => array( $setting_key => true ),
+ 'edit_link' => get_edit_post_link( $post_id, 'raw' ),
+ 'snapshot_publish_date' => $tomorrow,
+ ),
+ );
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ if ( ! method_exists( 'WP_Customize_Manager', 'prepare_setting_validity_for_js' ) ) {
+ unset( $expected_results['data']['setting_validities'] );
+ }
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+ $this->assertSame( $expected_results, $response );
+ $this->assertEquals( 'future', get_post_status( $post_id ) );
+ }
}
diff --git a/tests/php/test-class-customize-snapshot-manager.php b/tests/php/test-class-customize-snapshot-manager.php
index 24854795..62d60b93 100644
--- a/tests/php/test-class-customize-snapshot-manager.php
+++ b/tests/php/test-class-customize-snapshot-manager.php
@@ -190,7 +190,7 @@ function test_construct_with_customize_bootstrapped() {
/**
* Tests init hooks.
*
- * @covers Customize_Snapshot_Manager::init()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::init()
*/
public function test_init_hooks() {
$manager = new Customize_Snapshot_Manager( $this->plugin );
@@ -219,8 +219,8 @@ public function test_init_hooks() {
/**
* Tests init hooks.
*
- * @covers Customize_Snapshot_Manager::init()
- * @covers Customize_Snapshot_Manager::read_current_snapshot_uuid()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::init()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::read_current_snapshot_uuid()
*/
public function test_read_current_snapshot_uuid() {
$manager = new Customize_Snapshot_Manager( $this->plugin );
@@ -244,8 +244,8 @@ public function test_read_current_snapshot_uuid() {
/**
* Tests load_snapshot.
*
- * @covers Customize_Snapshot_Manager::init()
- * @covers Customize_Snapshot_Manager::load_snapshot()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::init()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::load_snapshot()
*/
public function test_load_snapshot() {
global $wp_actions;
@@ -272,8 +272,8 @@ public function test_load_snapshot() {
/**
* Tests setup_preview_ajax_requests.
*
- * @covers Customize_Snapshot_Manager::init()
- * @covers Customize_Snapshot_Manager::setup_preview_ajax_requests()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::init()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::setup_preview_ajax_requests()
*/
public function test_setup_preview_ajax_requests() {
wp_set_current_user( $this->user_id );
@@ -290,10 +290,40 @@ public function test_setup_preview_ajax_requests() {
$this->assertEquals( 5, has_action( 'parse_request', array( $manager, 'override_request_method' ) ) );
}
+
+ /**
+ * Tests setup_preview_ajax_requests for admin_ajax.
+ *
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::init()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::setup_preview_ajax_requests()
+ */
+ public function test_setup_preview_ajax_requests_for_admin_ajax() {
+ global $pagenow;
+ wp_set_current_user( $this->user_id );
+
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'GET';
+ $pagenow = 'admin-ajax.php'; // WPCS: Global override ok.
+ set_current_screen( 'admin-ajax' );
+ $this->assertTrue( is_admin() );
+
+ $_REQUEST['wp_customize_preview_ajax'] = 'true';
+ $_POST['customized'] = wp_slash( wp_json_encode( array( 'blogname' => 'Foo' ) ) );
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $manager->init();
+ do_action( 'admin_init' );
+ $this->do_customize_boot_actions( true );
+ $this->assertTrue( is_customize_preview() );
+ $this->assertFalse( has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
+ $this->assertFalse( has_action( 'parse_request', array( $manager, 'override_request_method' ) ) );
+ $this->assertEquals( 'GET', $_SERVER['REQUEST_METHOD'] );
+ $this->assertEquals( 'Foo', get_option( 'blogname' ) );
+ }
+
/**
* Tests override_request_method.
*
- * @covers Customize_Snapshot_Manager::override_request_method()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::override_request_method()
*/
public function test_override_request_method() {
global $wp;
@@ -323,12 +353,16 @@ public function test_override_request_method() {
$this->assertEquals( 'foo=1&bar=2', $_SERVER['QUERY_STRING'] );
$this->assertArrayHasKey( 'foo', $_GET );
$this->assertArrayHasKey( 'bar', $_GET );
+
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT';
+ $this->assertFalse( $manager->override_request_method() );
}
/**
* Tests doing_customize_save_ajax.
*
- * @covers Customize_Snapshot_Manager::doing_customize_save_ajax()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::doing_customize_save_ajax()
*/
public function test_doing_customize_save_ajax() {
$manager = new Customize_Snapshot_Manager( $this->plugin );
@@ -344,7 +378,7 @@ public function test_doing_customize_save_ajax() {
/**
* Tests ensure_customize_manager.
*
- * @covers Customize_Snapshot_Manager::ensure_customize_manager()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::ensure_customize_manager()
*/
public function test_ensure_customize_manager() {
global $wp_customize;
@@ -359,7 +393,7 @@ public function test_ensure_customize_manager() {
/**
* Tests is_theme_active.
*
- * @covers Customize_Snapshot_Manager::is_theme_active()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::is_theme_active()
*/
public function test_is_theme_active() {
global $wp_customize;
@@ -374,7 +408,7 @@ public function test_is_theme_active() {
/**
* Tests should_import_and_preview_snapshot.
*
- * @covers Customize_Snapshot_Manager::should_import_and_preview_snapshot()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::should_import_and_preview_snapshot()
*/
public function test_should_import_and_preview_snapshot() {
global $pagenow, $wp_customize;
@@ -431,7 +465,7 @@ public function test_should_import_and_preview_snapshot() {
/**
* Tests is_previewing_settings.
*
- * @covers Customize_Snapshot_Manager::is_previewing_settings()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::is_previewing_settings()
*/
public function test_is_previewing_settings() {
$_REQUEST['customize_snapshot_uuid'] = self::UUID;
@@ -448,7 +482,7 @@ public function test_is_previewing_settings() {
/**
* Tests is_previewing_settings.
*
- * @covers Customize_Snapshot_Manager::is_previewing_settings()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::is_previewing_settings()
*/
public function test_is_previewing_settings_via_preview_init() {
$manager = new Customize_Snapshot_Manager( $this->plugin );
@@ -460,25 +494,74 @@ public function test_is_previewing_settings_via_preview_init() {
/**
* Tests preview_snapshot_settings.
*
- * @covers Customize_Snapshot_Manager::preview_snapshot_settings()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::preview_snapshot_settings()
*/
public function test_preview_snapshot_settings() {
- $this->markTestIncomplete();
+ global $wp_actions;
+ $_REQUEST['customize_snapshot_uuid'] = self::UUID;
+ $this->manager->post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array(
+ 'blogname' => array( 'value' => 'Hello' ),
+ ),
+ 'status' => 'draft',
+ ) );
+
+ // Prevent init from calling preview_snapshot_settings straight away.
+ unset( $wp_actions['wp_loaded'] );
+
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $manager->init();
+ $manager->ensure_customize_manager();
+ do_action( 'customize_register', $manager->customize_manager );
+ $this->assertFalse( $manager->is_previewing_settings() );
+ $this->assertFalse( $manager->customize_manager->get_setting( 'blogname' )->dirty );
+ $this->assertNotEquals( 'Hello', get_option( 'blogname' ) );
+ $manager->preview_snapshot_settings();
+ $this->assertEquals( 'Hello', get_option( 'blogname' ) );
+ $this->assertTrue( $manager->customize_manager->get_setting( 'blogname' )->dirty );
}
/**
* Tests import_snapshot_data.
*
- * @covers Customize_Snapshot_Manager::import_snapshot_data()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::import_snapshot_data()
*/
public function test_import_snapshot_data() {
- $this->markTestIncomplete();
+ global $wp_actions;
+ $_REQUEST['customize_snapshot_uuid'] = self::UUID;
+ $this->manager->post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array(
+ 'blogname' => array( 'value' => 'Hello' ),
+ 'blogdescription' => array( 'value' => null ),
+ ),
+ 'status' => 'draft',
+ ) );
+
+ // Prevent init from calling import_snapshot_data straight away.
+ unset( $wp_actions['setup_theme'] );
+
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $manager->init();
+ $manager->ensure_customize_manager();
+ do_action( 'customize_register', $manager->customize_manager );
+
+ $this->assertArrayNotHasKey( 'customized', $_POST );
+ $this->assertArrayNotHasKey( 'customized', $_REQUEST );
+ $this->assertArrayNotHasKey( 'blogname', $manager->customize_manager->unsanitized_post_values() );
+ $this->assertArrayNotHasKey( 'blogdescription', $manager->customize_manager->unsanitized_post_values() );
+ $manager->import_snapshot_data();
+ $this->assertArrayHasKey( 'customized', $_POST );
+ $this->assertArrayHasKey( 'customized', $_REQUEST );
+ $this->assertArrayHasKey( 'blogname', $manager->customize_manager->unsanitized_post_values() );
+ $this->assertArrayNotHasKey( 'blogdescription', $manager->customize_manager->unsanitized_post_values() );
}
/**
* Tests add_widget_setting_preview_filters.
*
- * @covers Customize_Snapshot_Manager::add_widget_setting_preview_filters()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::add_widget_setting_preview_filters()
*/
public function test_add_widget_setting_preview_filters() {
$this->markTestIncomplete();
@@ -487,7 +570,7 @@ public function test_add_widget_setting_preview_filters() {
/**
* Tests add_nav_menu_setting_preview_filters.
*
- * @covers Customize_Snapshot_Manager::add_nav_menu_setting_preview_filters()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::add_nav_menu_setting_preview_filters()
*/
public function test_add_nav_menu_setting_preview_filters() {
$this->markTestIncomplete();
@@ -496,10 +579,39 @@ public function test_add_nav_menu_setting_preview_filters() {
/**
* Tests preview_early_nav_menus_in_customizer.
*
- * @covers Customize_Snapshot_Manager::preview_early_nav_menus_in_customizer()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::preview_early_nav_menus_in_customizer()
*/
public function test_preview_early_nav_menus_in_customizer() {
- $this->markTestIncomplete();
+ global $pagenow;
+ $pagenow = 'customize.php'; // WPCS: Global override ok.
+ set_current_screen( 'customize' );
+
+ $menu_id = -123;
+ $setting_id = sprintf( 'nav_menu[%d]', $menu_id );
+
+ $_REQUEST['customize_snapshot_uuid'] = self::UUID;
+ $this->manager->post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array(
+ $setting_id => array(
+ 'value' => array(
+ 'name' => 'Bar',
+ ),
+ ),
+ ),
+ 'status' => 'draft',
+ ) );
+
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $manager->init();
+ do_action( 'customize_register', $manager->customize_manager );
+
+ $setting = $manager->customize_manager->get_setting( $setting_id );
+ $this->assertInstanceOf( 'WP_Customize_Nav_Menu_Setting', $setting );
+ $nav_menu = wp_get_nav_menu_object( $menu_id );
+ $this->assertEquals( 'Bar', $nav_menu->name );
+
+ $this->assertInstanceOf( 'WP_Customize_Nav_Menu_Section', $manager->customize_manager->get_section( $setting_id ) );
}
/**
@@ -523,7 +635,7 @@ public function test_add_snapshot_uuid_to_return_url() {
/**
* Tests show_theme_switch_error.
*
- * @covers Customize_Snapshot_Manager::show_theme_switch_error()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::show_theme_switch_error()
*/
function test_show_theme_switch_error() {
$this->markTestIncomplete();
@@ -532,7 +644,7 @@ function test_show_theme_switch_error() {
/**
* Tests get_theme_switch_error.
*
- * @covers Customize_Snapshot_Manager::get_theme_switch_error()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::get_theme_switch_error()
*/
function test_get_theme_switch_error() {
$this->markTestIncomplete();
@@ -541,7 +653,7 @@ function test_get_theme_switch_error() {
/**
* Tests check_customize_publish_authorization.
*
- * @covers Customize_Snapshot_Manager::check_customize_publish_authorization()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::check_customize_publish_authorization()
*/
function test_check_customize_publish_authorization() {
$this->markTestIncomplete();
@@ -575,6 +687,39 @@ function test_enqueue_controls_scripts() {
$this->assertTrue( wp_style_is( 'customize-snapshots', 'enqueued' ) );
}
+ /**
+ * Test customize preview init.
+ *
+ * @see Customize_Snapshot_Manager::customize_preview_init()
+ */
+ function test_customize_preview_init() {
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $this->assertFalse( has_action( 'wp_enqueue_scripts', array( $manager, 'enqueue_preview_scripts' ) ) );
+ $manager->customize_preview_init();
+ $this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $manager, 'enqueue_preview_scripts' ) ) );
+ }
+
+ /**
+ * Test enqueue preview scripts.
+ *
+ * @see Customize_Snapshot_Manager::enqueue_preview_scripts()
+ */
+ function test_enqueue_preview_scripts() {
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $manager->ensure_customize_manager();
+ $manager->init();
+ $handle = 'customize-snapshots-preview';
+ $this->assertFalse( wp_scripts()->query( $handle, 'enqueued' ) );
+ $this->assertFalse( wp_styles()->query( $handle, 'enqueued' ) );
+ $manager->enqueue_preview_scripts();
+ $this->assertTrue( wp_scripts()->query( $handle, 'enqueued' ) );
+ $this->assertTrue( wp_styles()->query( $handle, 'enqueued' ) );
+
+ $after = wp_scripts()->get_data( $handle, 'after' );
+ $this->assertNotEmpty( $after );
+ $this->assertContains( 'CustomizeSnapshotsPreview', join( '', $after ) );
+ }
+
/**
* Test enqueue frontend scripts.
*
@@ -600,10 +745,11 @@ function test_enqueue_frontend_scripts() {
/**
* Test filter_customize_refresh_nonces.
*
- * @covers Customize_Snapshot_Manager::filter_customize_refresh_nonces()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::filter_customize_refresh_nonces()
*/
function test_filter_customize_refresh_nonces() {
- $this->markTestIncomplete();
+ $manager = new Customize_Snapshot_Manager( $this->plugin );
+ $this->assertArrayHasKey( 'snapshot', $manager->filter_customize_refresh_nonces( array() ) );
}
/**
@@ -621,7 +767,7 @@ function test_snapshot() {
/**
* Test publish snapshot with customize_save_after.
*
- * @covers Customize_Snapshot_Manager::publish_snapshot_with_customize_save_after()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::publish_snapshot_with_customize_save_after()
*/
function test_publish_snapshot_with_customize_save_after() {
wp_set_current_user( $this->user_id );
@@ -645,7 +791,7 @@ function test_publish_snapshot_with_customize_save_after() {
/**
* Test prepare_snapshot_post_content_for_publish.
*
- * @covers Customize_Snapshot_Manager::prepare_snapshot_post_content_for_publish()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::prepare_snapshot_post_content_for_publish()
*/
public function test_prepare_snapshot_post_content_for_publish() {
$snapshot_manager = get_plugin_instance()->customize_snapshot_manager;
@@ -676,7 +822,7 @@ public function test_prepare_snapshot_post_content_for_publish() {
/**
* Test save_settings_with_publish_snapshot.
*
- * @covers Customize_Snapshot_Manager::save_settings_with_publish_snapshot()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::save_settings_with_publish_snapshot()
*/
public function test_save_settings_with_publish_snapshot() {
$post_type = $this->manager->post_type;
@@ -740,7 +886,7 @@ public function test_save_settings_with_publish_snapshot() {
/**
* Test prepare_errors_for_response.
*
- * @covers Customize_Snapshot_Manager::prepare_errors_for_response()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::prepare_errors_for_response()
*/
public function test_prepare_errors_for_response() {
$this->markTestIncomplete();
@@ -749,7 +895,7 @@ public function test_prepare_errors_for_response() {
/**
* Tests generate_uuid.
*
- * @covers Customize_Snapshot_Manager::generate_uuid()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::generate_uuid()
*/
public function test_generate_uuid() {
$this->markTestIncomplete();
@@ -758,7 +904,7 @@ public function test_generate_uuid() {
/**
* Tests is_valid_uuid.
*
- * @covers Customize_Snapshot_Manager::is_valid_uuid()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::is_valid_uuid()
*/
public function test_is_valid_uuid() {
$this->markTestIncomplete();
@@ -814,7 +960,7 @@ public function test_customize_menu_return() {
/**
* Tests print_admin_bar_styles.
*
- * @covers Customize_Snapshot_Manager::print_admin_bar_styles()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::print_admin_bar_styles()
*/
public function test_print_admin_bar_styles() {
$manager = new Customize_Snapshot_Manager( $this->plugin );
@@ -828,7 +974,7 @@ public function test_print_admin_bar_styles() {
/**
* Test replace_customize_link.
*
- * @covers Customize_Snapshot_Manager::replace_customize_link()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::replace_customize_link()
*/
public function test_replace_customize_link() {
global $wp_admin_bar;
@@ -871,10 +1017,10 @@ public function test_replace_customize_link() {
/**
* Test misc admin bar extensions.
*
- * @covers Customize_Snapshot_Manager::add_post_edit_screen_link()
- * @covers Customize_Snapshot_Manager::add_snapshot_exit_link()
- * @covers Customize_Snapshot_Manager::add_resume_snapshot_link()
- * @covers Customize_Snapshot_Manager::remove_all_non_snapshot_admin_bar_links()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::add_post_edit_screen_link()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::add_snapshot_exit_link()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::add_resume_snapshot_link()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::remove_all_non_snapshot_admin_bar_links()
*/
public function test_add_post_edit_and_exit_links() {
global $wp_admin_bar;
@@ -921,7 +1067,7 @@ public function test_add_post_edit_and_exit_links() {
/**
* Test render templates.
*
- * @see Customize_Snapshot_Manager::render_templates()
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::render_templates()
*/
public function test_render_templates() {
ob_start();
@@ -930,5 +1076,47 @@ public function test_render_templates() {
ob_end_clean();
$this->assertContains( 'tmpl-snapshot-save', $templates );
$this->assertContains( 'tmpl-snapshot-dialog-error', $templates );
+ $this->assertContains( 'tmpl-snapshot-preview-link', $templates );
+ $this->assertContains( 'tmpl-snapshot-schedule-button', $templates );
+ $this->assertContains( 'tmpl-snapshot-schedule', $templates );
+ $this->assertContains( 'tmpl-snapshot-scheduled-countdown', $templates );
+ $this->assertContains( 'tmpl-snapshot-submit', $templates );
+ }
+
+ /**
+ * Test format_gmt_offset
+ *
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::format_gmt_offset()
+ */
+ public function test_format_gmt_offset() {
+ $offset = $this->manager->format_gmt_offset( 7.0 );
+ $this->assertEquals( '+7', $offset );
+ }
+
+ /**
+ * Test month choices
+ *
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::get_month_choices()
+ */
+ public function test_get_month_choices() {
+ $data = $this->manager->get_month_choices();
+ $this->assertArrayHasKey( 'month_choices', $data );
+ $this->assertCount( 12, $data['month_choices'] );
+ }
+
+ /**
+ * Test override post date if empty.
+ *
+ * @covers CustomizeSnapshots\Customize_Snapshot_Manager::override_post_date_default_data()
+ */
+ public function test_override_post_date_default_data() {
+ $post_id = $this->factory()->post->create();
+ $post = get_post( $post_id );
+ $post->post_date = $post->post_date_gmt = $post->post_modified = $post->post_modified_gmt = '0000-00-00 00:00:00';
+ $this->manager->override_post_date_default_data( $post );
+ $this->assertNotEquals( $post->post_date, '0000-00-00 00:00:00' );
+ $this->assertNotEquals( $post->post_date_gmt, '0000-00-00 00:00:00' );
+ $this->assertNotEquals( $post->post_modified, '0000-00-00 00:00:00' );
+ $this->assertNotEquals( $post->post_modified_gmt, '0000-00-00 00:00:00' );
}
}
diff --git a/tests/php/test-class-post-type.php b/tests/php/test-class-post-type.php
index b2027887..773c6209 100644
--- a/tests/php/test-class-post-type.php
+++ b/tests/php/test-class-post-type.php
@@ -63,7 +63,7 @@ public function test_register() {
/**
* Test filter_post_type_link.
*
- * @covers Post_Type::filter_post_type_link()
+ * @covers CustomizeSnapshots\Post_Type::filter_post_type_link()
*/
function test_filter_post_type_link() {
$post_type = new Post_Type( $this->plugin->customize_snapshot_manager );
@@ -382,7 +382,7 @@ public function test_find_post() {
/**
* Test getting the snapshot array out of the post_content.
*
- * @covers Post_Type::get_post_content()
+ * @covers CustomizeSnapshots\Post_Type::get_post_content()
* @expectedException \PHPUnit_Framework_Error_Warning
*/
public function test_get_post_content() {
@@ -626,7 +626,7 @@ function test_filter_user_has_cap() {
/**
* Tests display_post_states.
*
- * @covers Post_Type::display_post_states()
+ * @covers CustomizeSnapshots\Post_Type::display_post_states()
*/
public function test_display_post_states() {
$post_type = new Post_Type( $this->plugin->customize_snapshot_manager );
@@ -646,7 +646,7 @@ public function test_display_post_states() {
/**
* Tests show_publish_error_admin_notice.
*
- * @covers Post_Type::show_publish_error_admin_notice()
+ * @covers CustomizeSnapshots\Post_Type::show_publish_error_admin_notice()
*/
public function test_show_publish_error_admin_notice() {
global $current_screen, $post;
@@ -687,7 +687,7 @@ public function test_show_publish_error_admin_notice() {
/**
* Tests disable_revision_ui_for_published_posts.
*
- * @covers Post_Type::disable_revision_ui_for_published_posts()
+ * @covers CustomizeSnapshots\Post_Type::disable_revision_ui_for_published_posts()
*/
public function test_disable_revision_ui_for_published_posts() {
$post_type = new Post_Type( $this->plugin->customize_snapshot_manager );
@@ -716,7 +716,7 @@ public function test_disable_revision_ui_for_published_posts() {
/**
* Tests hide_disabled_publishing_actions.
*
- * @covers Post_Type::hide_disabled_publishing_actions()
+ * @covers CustomizeSnapshots\Post_Type::hide_disabled_publishing_actions()
*/
public function test_hide_disabled_publishing_actions() {
$post_type = new Post_Type( $this->plugin->customize_snapshot_manager );
diff --git a/tests/test-customize-snapshots.php b/tests/test-customize-snapshots.php
index bf391a53..0b326566 100644
--- a/tests/test-customize-snapshots.php
+++ b/tests/test-customize-snapshots.php
@@ -47,7 +47,7 @@ function test_customize_snapshots_php_version_text() {
/**
* Tests is_previewing_settings().
*
- * @covers is_previewing_settings()
+ * @see is_previewing_settings()
*/
public function test_is_previewing_settings() {
$this->assertFalse( is_previewing_settings() );
@@ -58,7 +58,7 @@ public function test_is_previewing_settings() {
/**
* Tests current_snapshot_uuid().
*
- * @covers current_snapshot_uuid()
+ * @see current_snapshot_uuid()
*/
public function test_current_snapshot_uuid() {
global $customize_snapshots_plugin;