diff --git a/.dev-lib b/.dev-lib
index 76f633ce..e65f5ff9 100644
--- a/.dev-lib
+++ b/.dev-lib
@@ -2,6 +2,10 @@ PATH_INCLUDES='*.* php js css tests'
WPCS_GIT_TREE=develop
ASSETS_DIR=wp-assets
+if [[ ${TRAVIS_PHP_VERSION:0:3} == "5.2" ]] || [[ ${TRAVIS_PHP_VERSION:0:3} == "5.3" ]]; then
+ DEV_LIB_SKIP="$DEV_LIB_SKIP,phpcs"
+fi
+
function after_wp_install {
echo "Installing REST API..."
svn export -q https://plugins.svn.wordpress.org/rest-api/trunk/ "$WP_CORE_DIR/src/wp-content/plugins/rest-api"
diff --git a/.travis.yml b/.travis.yml
index 70c258f2..8a3ccbd7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
sudo: false
+dist: precise
notifications:
email:
@@ -22,7 +23,7 @@ php:
env:
- WP_VERSION=trunk WP_MULTISITE=0
- WP_VERSION=latest WP_MULTISITE=0
- - WP_VERSION=4.6.1 WP_MULTISITE=0
+ - WP_VERSION=4.7.6 WP_MULTISITE=0
- WP_VERSION=latest WP_MULTISITE=1
install:
diff --git a/composer.json b/composer.json
index 89ddf97c..1f134354 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "xwp/wp-customize-snapshots",
"description": "Allow Customizer states to be drafted, and previewed with a private URL.",
- "version": "0.6.2",
+ "version": "0.7.0",
"type": "wordpress-plugin",
"homepage": "https://github.com/xwp/wp-customize-snapshots",
"license": "GPL-2.0+",
diff --git a/css/customize-snapshots-compat.css b/css/customize-snapshots-compat.css
new file mode 100644
index 00000000..e98c6f3e
--- /dev/null
+++ b/css/customize-snapshots-compat.css
@@ -0,0 +1,350 @@
+#snapshot-preview-link,
+#snapshot-expand-button {
+ float: right;
+ margin-top: 13px;
+ margin-right: 4px;
+ color: #656a6f;
+}
+
+#snapshot-expand-button {
+ display: block;
+}
+
+#snapshot-expand-button:hover,
+#snapshot-expand-button:focus,
+#snapshot-expand-button:active {
+ color: #191e23;
+}
+
+#snapshot-preview-link:hover,
+#snapshot-preview-link:focus,
+#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;
+}
+
+#snapshot-dialog-form h4 {
+ font-weight: bold;
+ font-size: 14px;
+ line-height: 1.5em;
+ margin: 0 0 .65em;
+ padding: .25em 0 0;
+}
+
+#snapshot-dialog-form p,
+#snapshot-dialog-link a,
+#snapshot-dialog-error p {
+ margin-top: .5em;
+}
+
+#snapshot-dialog-form label {
+ padding-bottom: 1em;
+}
+
+#snapshot-dialog-link {
+ word-wrap: break-word;
+}
+
+.wp-customizer.js .ui-dialog {
+ z-index: 999999;
+}
+
+@media screen and (max-width: 640px) {
+ #snapshot-save {
+ margin-top: 6px;
+ margin-right: 6px;
+ }
+}
+
+#customize-snapshot {
+ 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);
+ padding: 10px;
+ box-sizing: border-box;
+}
+
+#customize-snapshot .snapshot-schedule-title {
+ color: #555;
+}
+
+#customize-snapshot .snapshot-schedule-title h3 {
+ margin: .2em 2em .75em 0;
+}
+
+#customize-snapshot .snapshot-schedule-description {
+ margin-bottom: 0.5em;
+ margin-top: 0;
+}
+
+#customize-snapshot .timezone-info {
+ margin-top: 0.5em;
+ font-size: smaller;
+}
+
+#customize-snapshot 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;
+}
+
+#customize-snapshot a.snapshot-edit-link:focus,
+#customize-snapshot a.snapshot-edit-link:hover {
+ color: #0073aa;
+}
+
+#customize-snapshot a.snapshot-edit-link:before {
+ padding: 4px;
+ position: absolute;
+ top: 5px;
+ left: 6px;
+ -webkit-border-radius: 100%;
+ border-radius: 100%;
+}
+
+#customize-snapshot 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);
+}
+
+#customize-snapshot .accordion-section-title {
+ padding: 10px;
+}
+
+#customize-snapshot .reset-time {
+ font-weight: normal;
+ font-size: 80%;
+ display: none;
+}
+
+.snapshot-schedule-control.date-inputs {
+ display: flex;
+ display: -ms-flexbox;
+ align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ justify-content: flex-start;
+ -webkit-box-pack: start;
+ -ms-flex-pack: start;
+}
+
+.snapshot-schedule-control input.date-input {
+ -moz-appearance: textfield;
+ -webkit-appearance: textfield;
+ padding-left: 5px; /* 10px padding is not ideal for such small inputs */
+ padding-right: 5px;
+}
+
+.snapshot-schedule-control label {
+ display: inline-block; /* To align items when flex is not supported */
+}
+
+.snapshot-schedule-control .year.date-input {
+ min-width: 4em;
+}
+
+.snapshot-schedule-control input[type="number"] {
+ width: 100%;
+}
+
+.snapshot-schedule-control .time-special-char {
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.snapshot-schedule-control select {
+ height: 28px;
+}
+
+@media screen and ( max-width: 782px ) {
+ .snapshot-schedule-control select {
+ height: 40px;
+ }
+}
+
+.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;
+}
+
+.snapshot-control input[type="text"] {
+ width: 100%;
+ line-height: 18px;
+ margin: 0;
+}
+
+#customize-snapshot .snapshot-schedule-title h3 {
+ font-size: 16px;
+}
+
+#customize-snapshot .snapshot-controls {
+ list-style: none;
+ margin: 0;
+}
+
+.snapshot-future-date-notification.notice {
+ margin-bottom: 5px;
+ border-top: 1px solid #eee;
+ padding: 5px;
+}
+
+/*Status Button*/
+/** @todo Need to add snapshot specific class for all ui classes. **/
+
+#snapshot-status-button-wrapper {
+ float: right;
+ position: relative;
+ margin-top: 9px;
+ height: 28px;
+}
+
+#snapshot-status-button-wrapper .button-primary {
+ margin-top: 0;
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Chrome/Safari/Opera */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none;
+}
+
+.snapshot-status-button-wrapper .button:active{
+ -webkit-transform: none;
+ -moz-transform: none;
+ -ms-transform: none;
+ -o-transform: none;
+ transform: none; /* 4.7 added translateY(1px) */
+}
+
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: none;
+}
+
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ margin: 0;
+ margin-top: 2px;
+ overflow-x: hidden;
+ background: #FFFFFF;
+ border-top: 0;
+ border-radius: 0 0 5px 5px;
+ box-shadow: 0 1px 4px 0 rgba(33, 38, 34, .12), 0 2px 11px 0 rgba(30, 36, 37, .14)
+}
+
+.ui-selectmenu-menu .ui-menu li {
+ padding: 5px 10px 5px 5px;
+ margin: 0;
+}
+
+.ui-selectmenu-menu .ui-menu .ui-state-focus {
+ background: #0073aa;
+ color: #FFFFFF;
+ cursor: pointer;
+}
+
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+
+.ui-selectmenu-open {
+ display: block;
+}
+
+#snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons {
+ text-indent: 0;
+ float: right;
+ border-radius: 0 3px 3px 0;
+ padding-left: 0;
+ padding-right: 0;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ font-size: 20px;
+ width: 20px;
+}
+
+#snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons:before {
+ display: inline-block;
+ margin-left: -3px;
+}
+
+@media screen and ( max-width: 640px ) {
+ #snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons {
+ font-size: 17px;
+ }
+}
+
+.ui-selectmenu-button span.ui-selectmenu-text {
+ border-radius: 3px 0 0 3px;
+ opacity: 0;
+}
+
+.ui-selectmenu-menu.ui-front {
+ z-index: 999999;
+}
+
+.snapshot-status-button-overlay.button {
+ width: calc( 100% - 20px );
+ height: 28px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ border-radius: 3px 0 0 3px;
+ box-shadow: none;
+}
+
+#customize-header-actions .ui-selectmenu-button {
+ display: inline-block;
+ outline-width: 2px;
+ outline-offset: -2px;
+}
+
diff --git a/css/customize-snapshots.css b/css/customize-snapshots.css
index e98c6f3e..e623512c 100644
--- a/css/customize-snapshots.css
+++ b/css/customize-snapshots.css
@@ -1,350 +1,23 @@
-#snapshot-preview-link,
-#snapshot-expand-button {
- float: right;
- margin-top: 13px;
- margin-right: 4px;
- color: #656a6f;
-}
-
-#snapshot-expand-button {
- display: block;
-}
-
-#snapshot-expand-button:hover,
-#snapshot-expand-button:focus,
-#snapshot-expand-button:active {
- color: #191e23;
-}
-
-#snapshot-preview-link:hover,
-#snapshot-preview-link:focus,
-#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;
-}
-
-#snapshot-dialog-form h4 {
- font-weight: bold;
- font-size: 14px;
- line-height: 1.5em;
- margin: 0 0 .65em;
- padding: .25em 0 0;
-}
-
-#snapshot-dialog-form p,
-#snapshot-dialog-link a,
-#snapshot-dialog-error p {
- margin-top: .5em;
-}
-
-#snapshot-dialog-form label {
- padding-bottom: 1em;
-}
-
-#snapshot-dialog-link {
- word-wrap: break-word;
-}
-
-.wp-customizer.js .ui-dialog {
- z-index: 999999;
-}
-
-@media screen and (max-width: 640px) {
- #snapshot-save {
- margin-top: 6px;
- margin-right: 6px;
- }
-}
-
-#customize-snapshot {
- 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);
- padding: 10px;
- box-sizing: border-box;
-}
-
-#customize-snapshot .snapshot-schedule-title {
- color: #555;
-}
-
-#customize-snapshot .snapshot-schedule-title h3 {
- margin: .2em 2em .75em 0;
-}
-
-#customize-snapshot .snapshot-schedule-description {
- margin-bottom: 0.5em;
- margin-top: 0;
-}
-
-#customize-snapshot .timezone-info {
- margin-top: 0.5em;
- font-size: smaller;
-}
-
-#customize-snapshot 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;
-}
-
-#customize-snapshot a.snapshot-edit-link:focus,
-#customize-snapshot a.snapshot-edit-link:hover {
- color: #0073aa;
-}
-
-#customize-snapshot a.snapshot-edit-link:before {
- padding: 4px;
- position: absolute;
- top: 5px;
- left: 6px;
- -webkit-border-radius: 100%;
- border-radius: 100%;
-}
-
-#customize-snapshot 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);
-}
-
-#customize-snapshot .accordion-section-title {
- padding: 10px;
-}
-
-#customize-snapshot .reset-time {
- font-weight: normal;
- font-size: 80%;
- display: none;
-}
-
-.snapshot-schedule-control.date-inputs {
- display: flex;
- display: -ms-flexbox;
- align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- justify-content: flex-start;
- -webkit-box-pack: start;
- -ms-flex-pack: start;
-}
-
-.snapshot-schedule-control input.date-input {
- -moz-appearance: textfield;
- -webkit-appearance: textfield;
- padding-left: 5px; /* 10px padding is not ideal for such small inputs */
- padding-right: 5px;
-}
-.snapshot-schedule-control label {
- display: inline-block; /* To align items when flex is not supported */
+#customize-control-changeset_title {
+ margin-top: 15px;
}
-.snapshot-schedule-control .year.date-input {
- min-width: 4em;
+.snapshot-countdown-container {
+ margin-top: 10px;
}
-.snapshot-schedule-control input[type="number"] {
- width: 100%;
-}
-
-.snapshot-schedule-control .time-special-char {
- padding-left: 2px;
- padding-right: 2px;
-}
-
-.snapshot-schedule-control select {
- height: 28px;
-}
-
-@media screen and ( max-width: 782px ) {
- .snapshot-schedule-control select {
- height: 40px;
- }
-}
-
-.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;
-}
-
-.snapshot-control input[type="text"] {
- width: 100%;
- line-height: 18px;
- margin: 0;
-}
-
-#customize-snapshot .snapshot-schedule-title h3 {
- font-size: 16px;
-}
-
-#customize-snapshot .snapshot-controls {
- list-style: none;
- margin: 0;
-}
-
-.snapshot-future-date-notification.notice {
- margin-bottom: 5px;
- border-top: 1px solid #eee;
- padding: 5px;
-}
-
-/*Status Button*/
-/** @todo Need to add snapshot specific class for all ui classes. **/
-
-#snapshot-status-button-wrapper {
+.customize-control-inspect-changeset-link {
+ width: auto;
float: right;
- position: relative;
- margin-top: 9px;
- height: 28px;
+ margin-top: -31px;
}
-#snapshot-status-button-wrapper .button-primary {
- margin-top: 0;
- -webkit-touch-callout: none; /* iOS Safari */
- -webkit-user-select: none; /* Chrome/Safari/Opera */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none;
+.customize-control-inspect-changeset-link .dashicons {
+ text-decoration: none;
+ padding-right: 4px;
}
-.snapshot-status-button-wrapper .button:active{
- -webkit-transform: none;
- -moz-transform: none;
- -ms-transform: none;
- -o-transform: none;
- transform: none; /* 4.7 added translateY(1px) */
+.customize-control-another-changeset-link {
+ margin-top: 15px;
}
-
-.ui-selectmenu-menu {
- padding: 0;
- margin: 0;
- position: absolute;
- top: 0;
- left: 0;
- display: none;
-}
-
-.ui-selectmenu-menu .ui-menu {
- overflow: auto;
- margin: 0;
- margin-top: 2px;
- overflow-x: hidden;
- background: #FFFFFF;
- border-top: 0;
- border-radius: 0 0 5px 5px;
- box-shadow: 0 1px 4px 0 rgba(33, 38, 34, .12), 0 2px 11px 0 rgba(30, 36, 37, .14)
-}
-
-.ui-selectmenu-menu .ui-menu li {
- padding: 5px 10px 5px 5px;
- margin: 0;
-}
-
-.ui-selectmenu-menu .ui-menu .ui-state-focus {
- background: #0073aa;
- color: #FFFFFF;
- cursor: pointer;
-}
-
-.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
- font-size: 1em;
- font-weight: bold;
- line-height: 1.5;
- padding: 2px 0.4em;
- margin: 0.5em 0 0 0;
- height: auto;
- border: 0;
-}
-
-.ui-selectmenu-open {
- display: block;
-}
-
-#snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons {
- text-indent: 0;
- float: right;
- border-radius: 0 3px 3px 0;
- padding-left: 0;
- padding-right: 0;
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
- font-size: 20px;
- width: 20px;
-}
-
-#snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons:before {
- display: inline-block;
- margin-left: -3px;
-}
-
-@media screen and ( max-width: 640px ) {
- #snapshot-status-button-wrapper .ui-selectmenu-button span.dashicons {
- font-size: 17px;
- }
-}
-
-.ui-selectmenu-button span.ui-selectmenu-text {
- border-radius: 3px 0 0 3px;
- opacity: 0;
-}
-
-.ui-selectmenu-menu.ui-front {
- z-index: 999999;
-}
-
-.snapshot-status-button-overlay.button {
- width: calc( 100% - 20px );
- height: 28px;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- border-radius: 3px 0 0 3px;
- box-shadow: none;
-}
-
-#customize-header-actions .ui-selectmenu-button {
- display: inline-block;
- outline-width: 2px;
- outline-offset: -2px;
-}
-
diff --git a/customize-snapshots.php b/customize-snapshots.php
index 242d8dec..451f4cf3 100644
--- a/customize-snapshots.php
+++ b/customize-snapshots.php
@@ -3,7 +3,7 @@
* Plugin Name: Customize Snapshots
* Plugin URI: https://github.com/xwp/wp-customize-snapshots
* Description: Allow Customizer states to be drafted, and previewed with a private URL.
- * Version: 0.6.2
+ * Version: 0.7.0
* Author: XWP
* Author URI: https://xwp.co/
* License: GPLv2+
diff --git a/dev-lib b/dev-lib
index 24626547..52874e44 160000
--- a/dev-lib
+++ b/dev-lib
@@ -1 +1 @@
-Subproject commit 2462654769ad18e49ed835418104818ba5daed99
+Subproject commit 52874e44d9e737dfc8f1e9ca33381f45deb9b636
diff --git a/instance.php b/instance.php
index 350fa45c..50a61216 100644
--- a/instance.php
+++ b/instance.php
@@ -27,18 +27,11 @@ function get_plugin_instance() {
/**
* Convenience function for whether settings are being previewed.
*
- * @see Customize_Snapshot_Manager::is_previewing_settings()
- * @see Customize_Snapshot_Manager::preview_snapshot_settings()
- *
* @return bool Whether previewing settings.
*/
function is_previewing_settings() {
$manager = get_plugin_instance()->customize_snapshot_manager;
- if ( get_plugin_instance()->compat ) {
- return $manager->is_previewing_settings();
- } else {
- return ( isset( $manager->customize_manager ) && $manager->customize_manager->is_preview() ) || did_action( 'customize_preview_init' );
- }
+ return ( isset( $manager->customize_manager ) && $manager->customize_manager->is_preview() ) || did_action( 'customize_preview_init' );
}
/**
@@ -47,13 +40,14 @@ function is_previewing_settings() {
* @see Customize_Snapshot_Manager::$current_snapshot_uuid
*
* @return string|null The current snapshot UUID or null if no snapshot.
+ * @global \WP_Customize_Manager $wp_customize
*/
function current_snapshot_uuid() {
- $customize_snapshot_uuid = get_plugin_instance()->customize_snapshot_manager->current_snapshot_uuid;
- if ( empty( $customize_snapshot_uuid ) ) {
+ global $wp_customize;
+ if ( empty( $wp_customize ) ) {
return null;
} else {
- return $customize_snapshot_uuid;
+ return $wp_customize->changeset_uuid();
}
}
@@ -70,5 +64,5 @@ function is_back_compat() {
if ( false !== $pos ) {
$wp_version = substr( $wp_version, 0, $pos );
}
- return version_compare( $wp_version, '4.7', '<' );
+ return version_compare( $wp_version, '4.9', '<' );
}
diff --git a/js/compat/customize-snapshots-frontend.js b/js/compat/customize-snapshots-frontend.js
deleted file mode 100644
index aa3abbaa..00000000
--- a/js/compat/customize-snapshots-frontend.js
+++ /dev/null
@@ -1,335 +0,0 @@
-/* global jQuery, confirm */
-/* exported CustomizeSnapshotsFrontend */
-/* eslint consistent-this: [ "error", "section" ], no-magic-numbers: [ "error", { "ignore": [-1,0,1] } ] */
-/* eslint-disable no-alert */
-
-/*
- * The code here is derived from the initial Transactions pull request: https://github.com/xwp/wordpress-develop/pull/61
- * See https://github.com/xwp/wordpress-develop/blob/97fd5019c488a0713d34b517bdbff67c62c48a5d/src/wp-includes/js/customize-preview.js#L98-L111
- */
-
-var CustomizeSnapshotsFrontend = ( function( $ ) {
- 'use strict';
-
- var component = {
- data: {
- uuid: '',
- home_url: {
- scheme: '',
- host: '',
- path: ''
- },
- l10n: {
- restoreSessionPrompt: ''
- }
- }
- };
-
- /**
- * Init.
- *
- * @param {object} args Args.
- * @param {string} args.uuid UUID.
- * @returns {void}
- */
- component.init = function init( args ) {
- _.extend( component.data, args );
-
- component.hasSessionStorage = 'undefined' !== typeof sessionStorage;
-
- component.keepSessionAlive();
- component.rememberSessionSnapshot();
- component.injectSnapshotIntoLinks();
- component.handleExitSnapshotSessionLink();
- component.injectSnapshotIntoAjaxRequests();
- component.injectSnapshotIntoForms();
- };
-
- /**
- * Prompt to restore session.
- *
- * @returns {void}
- */
- component.keepSessionAlive = function keepSessionAlive() {
- var currentSnapshotUuid, urlParser, adminBarItem;
- if ( ! component.hasSessionStorage ) {
- return;
- }
- currentSnapshotUuid = sessionStorage.getItem( 'customize_snapshot_uuid' );
- if ( ! currentSnapshotUuid || component.data.uuid ) {
- return;
- }
-
- urlParser = document.createElement( 'a' );
- urlParser.href = location.href;
- if ( urlParser.search.length > 1 ) {
- urlParser.search += '&';
- }
- urlParser.search += 'customize_snapshot_uuid=' + encodeURIComponent( sessionStorage.getItem( 'customize_snapshot_uuid' ) );
-
- $( function() {
- adminBarItem = $( '#wp-admin-bar-resume-customize-snapshot' );
- if ( adminBarItem.length ) {
- adminBarItem.find( '> a' ).prop( 'href', urlParser.href );
- adminBarItem.show();
- } else if ( confirm( component.data.l10n.restoreSessionPrompt ) ) {
- location.replace( urlParser.href );
- } else {
- sessionStorage.removeItem( 'customize_snapshot_uuid' );
- }
- } );
- };
-
- /**
- * Remember the session's snapshot.
- *
- * Persist the snapshot UUID in session storage so that we can prompt to restore the snapshot query param if inadvertently dropped.
- *
- * @returns {void}
- */
- component.rememberSessionSnapshot = function rememberSessionSnapshot() {
- if ( ! component.hasSessionStorage || ! component.data.uuid ) {
- return;
- }
- sessionStorage.setItem( 'customize_snapshot_uuid', component.data.uuid );
- };
-
- /**
- * Inject the snapshot UUID into links in the document.
- *
- * @returns {void}
- */
- component.injectSnapshotIntoLinks = function injectSnapshotIntoLinks() {
- var linkSelectors = 'a, area';
-
- if ( ! component.data.uuid ) {
- return;
- }
- $( function() {
-
- // Inject links into initial document.
- $( document.body ).find( linkSelectors ).each( function() {
- component.injectSnapshotLinkParam( this );
- } );
-
- // Inject links for new elements added to the page
- if ( 'undefined' !== typeof MutationObserver ) {
- component.mutationObserver = new MutationObserver( function( mutations ) {
- _.each( mutations, function( mutation ) {
- $( mutation.target ).find( linkSelectors ).each( function() {
- component.injectSnapshotLinkParam( this );
- } );
- } );
- } );
- component.mutationObserver.observe( document.documentElement, {
- childList: true,
- subtree: true
- } );
- } else {
-
- // If mutation observers aren't available, fallback to just-in-time injection.
- $( document.documentElement ).on( 'click focus mouseover', linkSelectors, function() {
- component.injectSnapshotLinkParam( this );
- } );
- }
- } );
- };
-
- /**
- * Is matching base URL (host and path)?
- *
- * @param {HTMLAnchorElement} parsedUrl Parsed URL.
- * @param {string} parsedUrl.hostname Host.
- * @param {string} parsedUrl.pathname Path.
- * @returns {boolean} Whether matched.
- */
- component.isMatchingBaseUrl = function isMatchingBaseUrl( parsedUrl ) {
- return parsedUrl.hostname === component.data.home_url.host && 0 === parsedUrl.pathname.indexOf( component.data.home_url.path );
- };
-
- /**
- * Should the supplied link have a snapshot UUID added (or does it have one already)?
- *
- * @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
- * @param {string} element.search Query string.
- * @param {string} element.pathname Path.
- * @param {string} element.hostname Hostname.
- * @returns {boolean} Is appropriate for snapshot link.
- */
- component.shouldLinkHaveSnapshotParam = function shouldLinkHaveSnapshotParam( element ) {
- if ( ! component.isMatchingBaseUrl( element ) ) {
- return false;
- }
-
- // Skip wp login and signup pages.
- if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) ) {
- return false;
- }
-
- // Allow links to admin ajax as faux frontend URLs.
- if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) ) {
- return true;
- }
-
- // Disallow links to admin.
- if ( /\/wp-admin(\/|$)/.test( element.pathname ) ) {
- return false;
- }
-
- // Skip links in admin bar.
- if ( $( element ).closest( '#wpadminbar' ).length ) {
- return false;
- }
-
- return true;
- };
-
- /**
- * Return whether the supplied link element has the snapshot query param.
- *
- * @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
- * @param {object} element.search Query string.
- * @returns {boolean} Whether query param is present.
- */
- component.doesLinkHaveSnapshotQueryParam = function( element ) {
- return /(^|&)customize_snapshot_uuid=/.test( element.search.substr( 1 ) );
- };
-
- /**
- * Inject the customize_snapshot_uuid query param into links on the frontend.
- *
- * @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
- * @param {object} element.search Query string.
- * @returns {void}
- */
- component.injectSnapshotLinkParam = function injectSnapshotLinkParam( element ) {
- if ( component.doesLinkHaveSnapshotQueryParam( element ) || ! component.shouldLinkHaveSnapshotParam( element ) ) {
- return;
- }
-
- if ( element.search.length > 1 ) {
- element.search += '&';
- }
- element.search += 'customize_snapshot_uuid=' + encodeURIComponent( component.data.uuid );
- };
-
- /**
- * Handle electing to exit from the snapshot session.
- *
- * @returns {void}
- */
- component.handleExitSnapshotSessionLink = function handleExitSnapshotSessionLink() {
- $( function() {
- if ( ! component.hasSessionStorage ) {
- return;
- }
- $( '#wpadminbar' ).on( 'click', '#wp-admin-bar-exit-customize-snapshot', function() {
- sessionStorage.removeItem( 'customize_snapshot_uuid' );
- } );
- } );
- };
-
- /**
- * Inject the snapshot UUID into Ajax requests.
- *
- * @return {void}
- */
- component.injectSnapshotIntoAjaxRequests = function injectSnapshotIntoAjaxRequests() {
- $.ajaxPrefilter( component.prefilterAjax );
- };
-
- /**
- * Rewrite Ajax requests to inject Customizer state.
- *
- * @param {object} options Options.
- * @param {string} options.type Type.
- * @param {string} options.url URL.
- * @returns {void}
- */
- component.prefilterAjax = function prefilterAjax( options ) {
- var urlParser;
- if ( ! component.data.uuid ) {
- return;
- }
-
- urlParser = document.createElement( 'a' );
- urlParser.href = options.url;
-
- // Abort if the request is not for this site.
- if ( ! component.isMatchingBaseUrl( urlParser ) ) {
- return;
- }
-
- // Skip if snapshot UUID already in URL.
- if ( -1 !== urlParser.search.indexOf( 'customize_snapshot_uuid=' + component.data.uuid ) ) {
- return;
- }
-
- if ( urlParser.search.substr( 1 ).length > 0 ) {
- urlParser.search += '&';
- }
- urlParser.search += 'customize_snapshot_uuid=' + component.data.uuid;
-
- options.url = urlParser.href;
- };
-
- /**
- * Inject snapshot into forms, allowing preview to persist through submissions.
- *
- * @returns {void}
- */
- component.injectSnapshotIntoForms = function injectSnapshotIntoForms() {
- if ( ! component.data.uuid ) {
- return;
- }
- $( function() {
-
- // Inject inputs for forms in initial document.
- $( document.body ).find( 'form' ).each( function() {
- component.injectSnapshotFormInput( this );
- } );
-
- // Inject inputs for new forms added to the page.
- if ( 'undefined' !== typeof MutationObserver ) {
- component.mutationObserver = new MutationObserver( function( mutations ) {
- _.each( mutations, function( mutation ) {
- $( mutation.target ).find( 'form' ).each( function() {
- component.injectSnapshotFormInput( this );
- } );
- } );
- } );
- component.mutationObserver.observe( document.documentElement, {
- childList: true,
- subtree: true
- } );
- }
- } );
- };
-
- /**
- * Inject snapshot into form inputs.
- *
- * @param {HTMLFormElement} form Form.
- * @returns {void}
- */
- component.injectSnapshotFormInput = function injectSnapshotFormInput( form ) {
- var urlParser;
- if ( $( form ).find( 'input[name=customize_snapshot_uuid]' ).length > 0 ) {
- return;
- }
- urlParser = document.createElement( 'a' );
- urlParser.href = form.action;
- if ( ! component.isMatchingBaseUrl( urlParser ) ) {
- return;
- }
-
- $( form ).prepend( $( '', {
- type: 'hidden',
- name: 'customize_snapshot_uuid',
- value: component.data.uuid
- } ) );
- };
-
- return component;
-} )( jQuery );
-
diff --git a/js/compat/customize-snapshots-preview.js b/js/compat/customize-snapshots-preview.js
deleted file mode 100644
index 78aa8fbc..00000000
--- a/js/compat/customize-snapshots-preview.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/* global jQuery, JSON */
-/* exported CustomizeSnapshotsPreview */
-/* eslint consistent-this: [ "error", "section" ], no-magic-numbers: [ "error", { "ignore": [-1,0,1] } ] */
-
-/*
- * The code here is derived from Customize REST Resources: https://github.com/xwp/wp-customize-rest-resources
- */
-
-var CustomizeSnapshotsPreview = (function( api, $ ) {
- 'use strict';
-
- var component = {
- data: {
- home_url: {
- scheme: '',
- host: '',
- path: ''
- },
- rest_api_url: {
- scheme: '',
- host: '',
- path: ''
- },
- admin_ajax_url: {
- scheme: '',
- host: '',
- path: ''
- },
- initial_dirty_settings: []
- }
- };
-
- /**
- * Init.
- *
- * @param {object} args Args.
- * @param {string} args.uuid UUID.
- * @returns {void}
- */
- component.init = function init( args ) {
- _.extend( component.data, args );
-
- component.injectSnapshotIntoAjaxRequests();
- component.handleFormSubmissions();
- };
-
- /**
- * Get customize query vars.
- *
- * @see wp.customize.previewer.query
- *
- * @returns {{
- * customized: string,
- * nonce: string,
- * wp_customize: string,
- * theme: string
- * }} Query vars.
- */
- component.getCustomizeQueryVars = function getCustomizeQueryVars() {
- var customized = {};
- api.each( function( setting ) {
- if ( setting._dirty || -1 !== _.indexOf( component.data.initial_dirty_settings, setting.id ) ) {
- customized[ setting.id ] = setting.get();
- }
- } );
- return {
- wp_customize: 'on',
- theme: api.settings.theme.stylesheet,
- nonce: api.settings.nonce.preview,
- customized: JSON.stringify( customized )
- };
- };
-
- /**
- * Inject the snapshot UUID into Ajax requests.
- *
- * @return {void}
- */
- component.injectSnapshotIntoAjaxRequests = function injectSnapshotIntoAjaxRequests() {
- $.ajaxPrefilter( component.prefilterAjax );
- };
-
- /**
- * Rewrite Ajax requests to inject Customizer state.
- *
- * This will not work 100% of the time, such as if an Admin Ajax handler is
- * specifically looking for a $_GET param vs a $_POST param.
- *
- * @param {object} options Options.
- * @param {string} options.type Type.
- * @param {string} options.url URL.
- * @param {object} originalOptions Original options.
- * @param {XMLHttpRequest} xhr XHR.
- * @returns {void}
- */
- component.prefilterAjax = function prefilterAjax( options, originalOptions, xhr ) {
- var requestMethod, urlParser, queryVars, isMatchingHomeUrl, isMatchingRestUrl, isMatchingAdminAjaxUrl;
-
- urlParser = document.createElement( 'a' );
- urlParser.href = options.url;
-
- isMatchingHomeUrl = urlParser.host === component.data.home_url.host && 0 === urlParser.pathname.indexOf( component.data.home_url.path );
- isMatchingRestUrl = urlParser.host === component.data.rest_api_url.host && 0 === urlParser.pathname.indexOf( component.data.rest_api_url.path );
- isMatchingAdminAjaxUrl = urlParser.host === component.data.admin_ajax_url.host && 0 === urlParser.pathname.indexOf( component.data.admin_ajax_url.path );
-
- if ( ! isMatchingHomeUrl && ! isMatchingRestUrl && ! isMatchingAdminAjaxUrl ) {
- return;
- }
-
- requestMethod = options.type.toUpperCase();
-
- // Customizer currently requires POST requests, so use override (force Backbone.emulateHTTP).
- if ( 'POST' !== requestMethod ) {
- xhr.setRequestHeader( 'X-HTTP-Method-Override', requestMethod );
- options.type = 'POST';
- }
-
- if ( options.data && 'GET' === requestMethod ) {
- /*
- * Make sure the query vars for the REST API persist in GET (since
- * REST API explicitly look at $_GET['filter']).
- * We have to make sure the REST query vars are added as GET params
- * when the method is GET as otherwise they won't be parsed properly.
- * The issue lies in \WP_REST_Request::get_parameter_order() which
- * only is looking at \WP_REST_Request::$method instead of $_SERVER['REQUEST_METHOD'].
- * @todo Improve \WP_REST_Request::get_parameter_order() to be more aware of X-HTTP-Method-Override
- */
- if ( urlParser.search.substr( 1 ).length > 1 ) {
- urlParser.search += '&';
- }
- urlParser.search += options.data;
- }
-
- // Add Customizer post data.
- if ( options.data ) {
- options.data += '&';
- } else {
- options.data = '';
- }
- queryVars = component.getCustomizeQueryVars();
- queryVars.wp_customize_preview_ajax = 'true';
- options.data += $.param( queryVars );
- };
-
- /**
- * Handle form submissions.
- *
- * This fixes Core ticket {@link https://core.trac.wordpress.org/ticket/20714|#20714: Theme customizer: Impossible to preview a search results page}
- * Implements todo in {@link https://github.com/xwp/wordpress-develop/blob/4.5.3/src/wp-includes/js/customize-preview.js#L69-L73}
- *
- * @returns {void}
- */
- component.handleFormSubmissions = function handleFormSubmissions() {
- $( function() {
-
- // Defer so that we can be sure that our event handler will come after any other event handlers.
- _.defer( function() {
- component.replaceFormSubmitHandler();
- } );
- } );
- };
-
- /**
- * Replace form submit handler.
- *
- * @returns {void}
- */
- component.replaceFormSubmitHandler = function replaceFormSubmitHandler() {
- var body = $( document.body );
- body.off( 'submit.preview' );
- body.on( 'submit.preview', 'form', function( event ) {
- var urlParser;
-
- /*
- * If the default wasn't prevented already (in which case the form
- * submission is already being handled by JS), and if it has a GET
- * request method, then take the serialized form data and add it as
- * a query string to the action URL and send this in a url message
- * to the Customizer pane so that it will be loaded. If the form's
- * action points to a non-previewable URL, the the Customizer pane's
- * previewUrl setter will reject it so that the form submission is
- * a no-op, which is the same behavior as when clicking a link to an
- * external site in the preview.
- */
- if ( ! event.isDefaultPrevented() && 'GET' === this.method.toUpperCase() ) {
- urlParser = document.createElement( 'a' );
- urlParser.href = this.action;
- if ( urlParser.search.substr( 1 ).length > 1 ) {
- urlParser.search += '&';
- }
- urlParser.search += $( this ).serialize();
- api.preview.send( 'url', urlParser.href );
- }
-
- // Now preventDefault as is done on the normal submit.preview handler in customize-preview.js.
- event.preventDefault();
- } );
- };
-
- return component;
-} )( wp.customize, jQuery );
diff --git a/js/compat/customize-snapshots.js b/js/compat/customize-snapshots.js
deleted file mode 100644
index 311d0938..00000000
--- a/js/compat/customize-snapshots.js
+++ /dev/null
@@ -1,536 +0,0 @@
-/* global jQuery, wp, _customizeSnapshotsCompatSettings, JSON */
-/* eslint consistent-this: ["error", "snapshot"], no-magic-numbers: [ "error", { "ignore": [0,1,2] } ] */
-
-( function( api, $ ) {
- 'use strict';
-
- api.SnapshotsCompat = api.Snapshots.extend( {
-
- uuidParam: 'customize_snapshot_uuid',
-
- initialize: function initialize( snapshotsConfig ) {
- var snapshot = this;
-
- if ( _.isObject( snapshotsConfig ) ) {
- _.extend( snapshot.data, snapshotsConfig );
- }
-
- window._wpCustomizeControlsL10n.save = snapshot.data.i18n.publish;
- window._wpCustomizeControlsL10n.saved = snapshot.data.i18n.published;
-
- api.bind( 'ready', function() {
- api.state.create( 'snapshot-exists', snapshot.data.snapshotExists );
-
- if ( api.state( 'snapshot-exists' ).get() ) {
- api.state( 'saved' ).set( false );
- snapshot.resetSavedStateQuietly();
- }
- } );
-
- // Make sure that saved state is false so that Published button behaves as expected.
- api.bind( 'save', function() {
- api.state( 'saved' ).set( false );
- } );
-
- api.bind( 'change', function() {
- api.state( 'snapshot-saved' ).set( false );
- } );
-
- api.bind( 'saved', function( response ) {
- var url = window.location.href,
- updatedUrl,
- urlParts;
-
- // Update the UUID.
- if ( response.new_customize_snapshot_uuid ) {
- snapshot.data.uuid = response.new_customize_snapshot_uuid;
- snapshot.previewLink.attr( 'target', snapshot.data.uuid );
- }
-
- snapshot.removeParamFromClose( 'customize_snapshot_uuid' );
-
- api.state( 'snapshot-exists' ).set( false );
-
- // Replace the history state with an updated Customizer URL that does not include the Snapshot UUID.
- urlParts = url.split( '?' );
- if ( history.replaceState && urlParts[1] ) {
- updatedUrl = urlParts[0] + '?' + _.filter( urlParts[1].split( '&' ), function( queryPair ) {
- return ! /^(customize_snapshot_uuid)=/.test( queryPair );
- } ).join( '&' );
- updatedUrl = updatedUrl.replace( /\?$/, '' );
- if ( updatedUrl !== url ) {
- history.replaceState( {}, document.title, updatedUrl );
- }
- }
- } );
-
- api.Snapshots.prototype.initialize.call( snapshot, snapshotsConfig );
- },
-
- /**
- * Update button text.
- *
- * @returns {void}
- */
- updateButtonText: function updateButtonText() {
- var snapshot = this, date = snapshot.getDateFromInputs();
- if ( snapshot.isFutureDate() && date && snapshot.data.currentUserCanPublish ) {
- snapshot.snapshotButton.text( snapshot.data.i18n.scheduleButton );
- } else {
- snapshot.snapshotButton.text( api.state( 'snapshot-exists' ).get() ? snapshot.data.i18n.updateButton : snapshot.data.i18n.saveButton );
- }
- },
-
- /**
- * Make the AJAX request to update/save a snapshot.
- *
- * @param {object} options Options.
- * @param {string} options.status The post status for the snapshot.
- * @return {void}
- */
- sendUpdateSnapshotRequest: function sendUpdateSnapshotRequest( options ) {
- var snapshot = this,
- spinner = $( '#customize-header-actions' ).find( '.spinner' ),
- request, data;
-
- data = _.extend(
- {
- status: 'draft'
- },
- api.previewer.query(),
- options,
- {
- nonce: api.settings.nonce.snapshot,
- customize_snapshot_uuid: snapshot.data.uuid
- }
- );
-
- request = wp.ajax.post( 'customize_update_snapshot', data );
-
- spinner.addClass( 'is-active' );
- request.always( function( response ) {
- spinner.removeClass( 'is-active' );
- if ( response.edit_link ) {
- snapshot.data.editLink = response.edit_link;
- }
- if ( response.snapshot_publish_date ) {
- snapshot.data.publishDate = response.snapshot_publish_date;
- }
- if ( response.title ) {
- snapshot.data.title = response.title;
- }
- snapshot.updateSnapshotEditControls();
- snapshot.data.dirty = false;
-
- // @todo Remove privateness from _handleSettingValidities in Core.
- if ( api._handleSettingValidities && response.setting_validities ) {
- api._handleSettingValidities( {
- settingValidities: response.setting_validities,
- focusInvalidControl: true
- } );
- }
- } );
-
- request.done( function( response ) {
- var url = api.previewer.previewUrl(),
- regex = new RegExp( '([?&])customize_snapshot_uuid=.*?(&|$)', 'i' ),
- notFound = -1,
- separator = url.indexOf( '?' ) !== notFound ? '&' : '?',
- customizeUrl = window.location.href,
- customizeSeparator = customizeUrl.indexOf( '?' ) !== notFound ? '&' : '?';
-
- if ( url.match( regex ) ) {
- url = url.replace( regex, '$1customize_snapshot_uuid=' + encodeURIComponent( snapshot.data.uuid ) + '$2' );
- } else {
- url = url + separator + 'customize_snapshot_uuid=' + encodeURIComponent( snapshot.data.uuid );
- }
-
- // Change the save button text to update.
- api.state( 'snapshot-exists' ).set( true );
-
- // Replace the history state with an updated Customizer URL that includes the Snapshot UUID.
- if ( history.replaceState && ! customizeUrl.match( regex ) ) {
- customizeUrl += customizeSeparator + 'customize_snapshot_uuid=' + encodeURIComponent( snapshot.data.uuid );
- history.replaceState( {}, document.title, customizeUrl );
- }
-
- api.state( 'snapshot-saved' ).set( true );
- if ( 'pending' === data.status ) {
- api.state( 'snapshot-submitted' ).set( true );
- }
- snapshot.resetSavedStateQuietly();
-
- // Trigger an event for plugins to use.
- api.trigger( 'customize-snapshots-update', {
- previewUrl: url,
- customizeUrl: customizeUrl,
- uuid: snapshot.data.uuid,
- response: response
- } );
- } );
-
- request.fail( function( response ) {
- var id = 'snapshot-dialog-error',
- snapshotDialogShareError = wp.template( id ),
- messages = snapshot.data.i18n.errorMsg,
- invalidityCount = 0,
- dialogElement;
-
- if ( response.setting_validities ) {
- invalidityCount = _.size( response.setting_validities, function( validity ) {
- return true !== validity;
- } );
- }
-
- /*
- * Short-circuit if there are setting validation errors, since the error messages
- * will be displayed with the controls themselves. Eventually, once we have
- * a global notification area in the Customizer, we can eliminate this
- * short-circuit and instead display the messages in there.
- * See https://core.trac.wordpress.org/ticket/35210
- */
- if ( invalidityCount > 0 ) {
- return;
- }
-
- if ( response.errors ) {
- messages += ' ' + _.pluck( response.errors, 'message' ).join( ' ' );
- }
-
- // Insert the snapshot dialog error template.
- dialogElement = $( '#' + id );
- if ( ! dialogElement.length ) {
- dialogElement = $( snapshotDialogShareError( {
- title: snapshot.data.i18n.errorTitle,
- message: messages
- } ) );
- $( 'body' ).append( dialogElement );
- }
-
- // Open the dialog.
- dialogElement.dialog( {
- autoOpen: true,
- modal: true
- } );
- } );
-
- return request;
- },
-
- /**
- * Amend the preview query so we can update the snapshot during `customize_save`.
- *
- * @return {void}
- */
- extendPreviewerQuery: function extendPreviewerQuery() {
- var snapshot = this, originalQuery = api.previewer.query;
-
- api.previewer.query = function() {
- var retval = originalQuery.apply( this, arguments );
- retval.customizer_state_query_vars = JSON.stringify( snapshot.getStateQueryVars() );
-
- if ( api.state( 'snapshot-exists' ).get() ) {
- retval.customize_snapshot_uuid = snapshot.data.uuid;
- if ( snapshot.snapshotTitle && snapshot.snapshotTitle.val() ) {
- retval.title = snapshot.snapshotTitle.val();
- }
- }
- return retval;
- };
- },
-
- /**
- * Create the snapshot buttons.
- *
- * @return {void}
- */
- addButtons: function addButtons() {
- var snapshot = this,
- header = $( '#customize-header-actions' ),
- disableButton = true,
- templateData = {}, setPreviewLinkHref, currentTheme,
- savedPreviewingTheme, themeNotActiveOrSaved;
-
- snapshot.publishButton = header.find( '#save' );
- snapshot.spinner = header.find( '.spinner' );
- snapshot.dirtyScheduleDate = new api.Value();
-
- // Save/update button.
- if ( api.state( 'snapshot-exists' ).get() ) {
- if ( 'future' === snapshot.data.postStatus ) {
- templateData.buttonText = snapshot.data.i18n.scheduleButton;
- } else {
- templateData.buttonText = snapshot.data.i18n.updateButton;
- }
- } else {
- templateData.buttonText = snapshot.data.i18n.saveButton;
- }
-
- snapshot.snapshotButton = $( $.trim( wp.template( 'snapshot-save' )( templateData ) ) );
-
- if ( ! snapshot.data.currentUserCanPublish ) {
- snapshot.snapshotButton.attr( 'title', api.state( 'snapshot-exists' ).get() ? snapshot.data.i18n.permsMsg.update : snapshot.data.i18n.permsMsg.save );
- }
-
- currentTheme = api.settings.theme.stylesheet; // Or previewing theme.
- savedPreviewingTheme = snapshot.data.previewingTheme;
- themeNotActiveOrSaved = ! api.state( 'activated' ).get() && ! savedPreviewingTheme;
- snapshot.isNotSavedPreviewingTheme = savedPreviewingTheme && savedPreviewingTheme !== currentTheme;
-
- if ( themeNotActiveOrSaved || snapshot.isNotSavedPreviewingTheme ) {
- disableButton = false;
- }
-
- snapshot.snapshotButton.prop( 'disabled', disableButton );
-
- snapshot.snapshotButton.on( 'click', function( event ) {
- var status;
- event.preventDefault();
- status = snapshot.isFutureDate() ? 'future' : 'draft';
-
- snapshot.snapshotButton.prop( 'disabled', true );
- snapshot.updateSnapshot( status ).done( function() {
- snapshot.snapshotButton.prop( 'disabled', true );
- } ).fail( function() {
- snapshot.snapshotButton.prop( 'disabled', false );
- } );
- } );
-
- snapshot.snapshotButton.insertAfter( snapshot.publishButton );
-
- // Preview link.
- snapshot.previewLink = $( $.trim( wp.template( 'snapshot-preview-link' )() ) );
- snapshot.previewLink.toggle( api.state( 'snapshot-saved' ).get() );
- snapshot.previewLink.attr( 'target', snapshot.data.uuid );
- setPreviewLinkHref = _.debounce( function() {
- if ( api.state( 'snapshot-exists' ).get() ) {
- snapshot.previewLink.attr( 'href', snapshot.getSnapshotFrontendPreviewUrl() );
- } else {
- snapshot.previewLink.attr( 'href', snapshot.frontendPreviewUrl.get() );
- }
- } );
- snapshot.frontendPreviewUrl.bind( setPreviewLinkHref );
- setPreviewLinkHref();
- api.state.bind( 'change', setPreviewLinkHref );
- api.bind( 'saved', setPreviewLinkHref );
- snapshot.snapshotButton.after( snapshot.previewLink );
- api.state( 'snapshot-saved' ).bind( function( saved ) {
- snapshot.previewLink.toggle( saved );
- } );
-
- // Edit button.
- snapshot.snapshotExpandButton = $( $.trim( wp.template( 'snapshot-expand-button' )( {} ) ) );
- snapshot.snapshotExpandButton.insertAfter( snapshot.snapshotButton );
-
- if ( ! snapshot.data.editLink ) {
- snapshot.snapshotExpandButton.hide();
- }
-
- api.state( 'change', function() {
- snapshot.snapshotExpandButton.toggle( api.state( 'snapshot-saved' ).get() && api.state( 'snapshot-exists' ).get() );
- } );
-
- api.state( 'snapshot-exists' ).bind( function( exist ) {
- snapshot.snapshotExpandButton.toggle( exist );
- } );
-
- api.state( 'snapshot-saved' ).bind( function( saved ) {
- snapshot.snapshotButton.prop( 'disabled', saved );
- } );
-
- api.state( 'saved' ).bind( function( saved ) {
- if ( saved ) {
- snapshot.snapshotButton.prop( 'disabled', true );
- }
- } );
- api.bind( 'change', function() {
- snapshot.snapshotButton.prop( 'disabled', false );
- } );
-
- api.state( 'snapshot-exists' ).bind( function( exists ) {
- var buttonText, permsMsg;
- if ( exists ) {
- buttonText = snapshot.data.i18n.updateButton;
- permsMsg = snapshot.data.i18n.permsMsg.update;
- } else {
- buttonText = snapshot.data.i18n.saveButton;
- permsMsg = snapshot.data.i18n.permsMsg.save;
- }
-
- snapshot.snapshotButton.text( buttonText );
- if ( ! snapshot.data.currentUserCanPublish ) {
- snapshot.snapshotButton.attr( 'title', permsMsg );
- }
- } );
-
- snapshot.editControlSettings.bind( 'change', function() {
- snapshot.snapshotButton.prop( 'disabled', false );
- snapshot.updateButtonText();
- } );
- snapshot.dirtyScheduleDate.bind( function( dirty ) {
- var date;
- if ( dirty ) {
- date = snapshot.getDateFromInputs();
- if ( ! date || ! snapshot.data.currentUserCanPublish ) {
- return;
- }
- snapshot.snapshotButton.text( snapshot.data.i18n.scheduleButton );
- } else {
- snapshot.updateButtonText();
- }
- } );
-
- // Submit for review button.
- if ( ! snapshot.data.currentUserCanPublish ) {
- snapshot.addSubmitButton();
- }
-
- header.addClass( 'button-added' );
- },
-
- /**
- * Silently update the saved state to be true without triggering the
- * changed event so that the AYS beforeunload dialog won't appear
- * if no settings have been changed after saving a snapshot. Note
- * that it would be better if jQuery's callbacks allowed them to
- * disabled and then re-enabled later, for example:
- * wp.customize.state.topics.change.disable();
- * wp.customize.state( 'saved' ).set( true );
- * wp.customize.state.topics.change.enable();
- * But unfortunately there is no such enable method.
- *
- * @return {void}
- */
- resetSavedStateQuietly: function resetSavedStateQuietly() {
- api.state( 'saved' )._value = true;
- },
-
- /**
- * Overrides the autoSaveEditBox method used in api.Snapshots
- * because we do not auto save in < 4.7.
- *
- * @inheritdoc
- */
- autoSaveEditBox: function autoSaveEditor() {
-
- },
-
- /**
- * Renders snapshot schedule and handles it's events.
- *
- * @returns {void}
- */
- editSnapshotUI: function editSnapshotUI() {
- var snapshot = this;
- api.Snapshots.prototype.editSnapshotUI.call( snapshot );
-
- api.state( 'saved' ).bind( function( saved ) {
- if ( saved && ! _.isEmpty( snapshot.editContainer ) ) {
- snapshot.data.dirty = false;
- snapshot.data.publishDate = snapshot.getCurrentTime();
- snapshot.snapshotEditContainerDisplayed.set( false );
- snapshot.updateSnapshotEditControls();
- }
- } );
- },
-
- /**
- * Updates snapshot schedule with `snapshot.data`.
- *
- * @return {void}
- */
- updateSnapshotEditControls: function updateSnapshotEditControls() {
- var snapshot = this, parsed,
- sliceBegin = 0,
- sliceEnd = -2;
-
- if ( _.isEmpty( snapshot.editContainer ) ) {
- return;
- }
-
- if ( snapshot.data.currentUserCanPublish ) {
- if ( '0000-00-00 00:00:00' === snapshot.data.publishDate ) {
- snapshot.data.publishDate = snapshot.getCurrentTime();
- }
-
- // Normalize date with seconds removed.
- snapshot.data.publishDate = snapshot.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
- parsed = snapshot.parseDateTime( snapshot.data.publishDate );
-
- // Update date controls.
- snapshot.schedule.inputs.each( function() {
- var input = $( this ),
- fieldName = input.data( 'date-input' );
-
- $( this ).val( parsed[fieldName] );
- } );
- }
-
- snapshot.editContainer.find( 'a.snapshot-edit-link' )
- .attr( 'href', snapshot.data.editLink )
- .show();
- if ( ! _.isEmpty( snapshot.data.title ) ) {
- snapshot.snapshotTitle.val( snapshot.data.title );
- }
- snapshot.populateSetting();
- },
-
- /**
- * Populate setting value from the inputs.
- *
- * @returns {void}
- */
- populateSetting: function populateSetting() {
- var snapshot = this,
- date = snapshot.getDateFromInputs(),
- scheduled, isDirtyDate;
-
- snapshot.editControlSettings( 'title' ).set( snapshot.snapshotTitle.val() );
-
- if ( ! date || ! snapshot.data.currentUserCanPublish ) {
- return;
- }
-
- date.setSeconds( 0 );
- scheduled = snapshot.formatDate( date ) !== snapshot.data.publishDate;
-
- isDirtyDate = scheduled && snapshot.isFutureDate();
- snapshot.dirtyScheduleDate.set( isDirtyDate );
- snapshot.editControlSettings( 'date' ).set( snapshot.formatDate( date ) );
-
- snapshot.updateCountdown();
- snapshot.editContainer.find( '.reset-time' ).toggle( scheduled );
- },
-
- /**
- * Parse query string.
- *
- * Polyfill for function was introduced into core in 4.7 as wp.customize.utils.parseQueryString.
- *
- * @param {string} queryString Query string.
- * @returns {object} Parsed query string.
- */
- parseQueryString: function parseQueryString( queryString ) {
- var queryParams = {};
- _.each( queryString.split( '&' ), function( pair ) {
- var parts, key, value;
- parts = pair.split( '=', 2 );
- if ( ! parts[0] ) {
- return;
- }
- key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
- key = key.replace( / /g, '_' ); // What PHP does.
- if ( _.isUndefined( parts[1] ) ) {
- value = null;
- } else {
- value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
- }
- queryParams[ key ] = value;
- } );
- return queryParams;
- }
- } );
-
- api.snapshotsCompat = new api.SnapshotsCompat( _customizeSnapshotsCompatSettings );
-
-} )( wp.customize, jQuery );
diff --git a/js/customize-migrate.js b/js/customize-migrate.js
deleted file mode 100644
index d4183b25..00000000
--- a/js/customize-migrate.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* global jQuery, wp */
-(function( $ ) {
- 'use strict';
- var component = {
- doingAjax: false,
- postMigrationCount: 5
- };
-
- /**
- * Initialize js.
- *
- * @return {void}
- */
- component.init = function() {
- $( function() {
- component.el = $( '#customize-snapshot-migration' );
- component.bindClick();
- component.spinner = $( '.spinner.customize-snapshot-spinner' );
- component.spinner.css( 'margin', '0' );
- } );
- };
-
- /**
- * Bind migrate click event.
- *
- * @return {void}
- */
- component.bindClick = function() {
- component.el.click( function() {
- if ( component.doingAjax ) {
- return;
- }
- component.spinner.css( 'visibility', 'visible' );
- component.doingAjax = true;
- component.migrate( component.el.data( 'nonce' ), component.postMigrationCount );
- } );
- };
-
- /**
- * Initiate migrate ajax request.
- *
- * @param {String} nonce Nonce.
- * @param {Number} limit Limit for migrate posts.
- *
- * @return {void}
- */
- component.migrate = function( nonce, limit ) {
- var request,
- requestData = {
- nonce: nonce,
- limit: limit
- };
-
- request = wp.ajax.post( 'customize_snapshot_migration', requestData );
-
- request.done( function( data ) {
- var outerDiv = $( 'div.customize-snapshot-migration' ), delay = 100, newLimit;
- if ( data.remaining_posts ) {
- newLimit = data.remaining_posts > limit ? limit : data.remaining_posts;
- _.delay( component.migrate, delay, nonce, newLimit );
- } else {
- component.spinner.css( 'visibility', 'hidden' );
- outerDiv.removeClass( 'notice-error' ).addClass( 'notice-success' ).find( 'p' ).html( component.el.data( 'migration-success' ) );
- component.doingAjax = false;
- }
- } );
-
- request.fail( function() {
- component.spinner.css( 'visibility', 'initial' );
- component.doingAjax = false;
- if ( window.console ) {
- window.console.error( 'Migration ajax failed. Click notice to start it again.' );
- }
- } );
- };
-
- component.init();
-
-})( jQuery );
diff --git a/js/customize-snapshots-compat.js b/js/customize-snapshots-compat.js
new file mode 100644
index 00000000..ea903cdb
--- /dev/null
+++ b/js/customize-snapshots-compat.js
@@ -0,0 +1,1223 @@
+/* global jQuery, wp, JSON */
+/* eslint no-magic-numbers: [ "error", { "ignore": [0,1,-1] } ], consistent-this: [ "error", "snapshot" ] */
+
+(function( api, $ ) {
+ 'use strict';
+
+ var escKeyCode = 27;
+
+ api.Snapshots = api.Class.extend( {
+
+ data: {
+ action: '',
+ uuid: '',
+ editLink: '',
+ title: '',
+ publishDate: '',
+ postStatus: '',
+ currentUserCanPublish: true,
+ initialServerDate: '',
+ initialServerTimestamp: 0,
+ initialClientTimestamp: 0,
+ previewingTheme: '',
+ i18n: {},
+ dirty: false
+ },
+
+ uuidParam: 'customize_changeset_uuid',
+
+ initialize: function initialize( snapshotsConfig ) {
+ var snapshot = this;
+
+ snapshot.schedule = {};
+
+ if ( _.isObject( snapshotsConfig ) ) {
+ _.extend( snapshot.data, snapshotsConfig );
+ }
+
+ // Set the initial client timestamp.
+ snapshot.data.initialClientTimestamp = snapshot.dateValueOf();
+
+ api.bind( 'ready', function() {
+ api.state.create( 'snapshot-exists', false );
+ api.state.create( 'snapshot-saved', true );
+ api.state.create( 'snapshot-submitted', true );
+
+ snapshot.data.uuid = snapshot.data.uuid || api.settings.changeset.uuid;
+ snapshot.data.title = snapshot.data.title || snapshot.data.uuid;
+
+ snapshot.editBoxAutoSaveTriggered = false;
+
+ if ( api.state.has( 'changesetStatus' ) && api.state( 'changesetStatus' ).get() ) {
+ api.state( 'snapshot-exists' ).set( true );
+ }
+
+ snapshot.extendPreviewerQuery();
+
+ snapshot.editControlSettings = new api.Values();
+ snapshot.editControlSettings.create( 'title', snapshot.data.title );
+ snapshot.editControlSettings.create( 'date', snapshot.data.publishDate );
+
+ api.bind( 'change', function() {
+ api.state( 'snapshot-submitted' ).set( false );
+ } );
+
+ snapshot.frontendPreviewUrl = new api.Value( api.previewer.previewUrl.get() );
+ snapshot.frontendPreviewUrl.link( api.previewer.previewUrl );
+ snapshot.isNotSavedPreviewingTheme = false;
+
+ snapshot.addButtons();
+ snapshot.editSnapshotUI();
+ snapshot.prefilterAjax();
+
+ api.trigger( 'snapshots-ready', snapshot );
+ } );
+
+ api.bind( 'save', function( request ) {
+
+ request.fail( function( response ) {
+ var id = '#snapshot-dialog-error',
+ snapshotDialogPublishError = wp.template( 'snapshot-dialog-error' );
+
+ if ( response.responseText ) {
+
+ // Insert the dialog error template.
+ if ( 0 === $( id ).length ) {
+ $( 'body' ).append( snapshotDialogPublishError( {
+ title: snapshot.data.i18n.publish,
+ message: api.state( 'snapshot-exists' ).get() ? snapshot.data.i18n.permsMsg.update : snapshot.data.i18n.permsMsg.save
+ } ) );
+ }
+
+ snapshot.spinner.removeClass( 'is-active' );
+
+ $( id ).dialog( {
+ autoOpen: true,
+ modal: true
+ } );
+ }
+ } );
+
+ return request;
+ } );
+ },
+
+ /**
+ * Get state query vars.
+ *
+ * @return {{}} Query vars for scroll, device, url, and autofocus.
+ */
+ getStateQueryVars: function() {
+ var snapshot = this, queryVars;
+
+ queryVars = {
+ 'autofocus[control]': null,
+ 'autofocus[section]': null,
+ 'autofocus[panel]': null
+ };
+
+ queryVars.scroll = parseInt( api.previewer.scroll, 10 ) || 0;
+ queryVars.device = api.previewedDevice.get();
+ queryVars.url = api.previewer.previewUrl.get();
+
+ if ( ! api.state( 'activated' ).get() || snapshot.isNotSavedPreviewingTheme ) {
+ queryVars.previewing_theme = true;
+ }
+
+ _.find( [ 'control', 'section', 'panel' ], function( constructType ) {
+ var found = false;
+ api[ constructType ].each( function( construct ) { // @todo Core needs to support more Backbone methods on wp.customize.Values().
+ if ( ! found && construct.expanded && construct.expanded.get() ) {
+ queryVars[ 'autofocus[' + constructType + ']' ] = construct.id;
+ found = true;
+ }
+ } );
+ return found;
+ } );
+
+ return queryVars;
+ },
+
+ /**
+ * Update snapshot.
+ *
+ * @param {string} status post status.
+ * @returns {jQuery.promise} Request or promise.
+ */
+ updateSnapshot: function updateSnapshot( status ) {
+ var snapshot = this, inputDate,
+ deferred = new $.Deferred(),
+ request,
+ requestData = {
+ status: status
+ };
+
+ if ( snapshot.statusButton && snapshot.statusButton.needConfirm ) {
+ snapshot.statusButton.disbleButton.set( false );
+ snapshot.statusButton.updateButtonText( 'confirm-text' );
+ snapshot.statusButton.needConfirm = false;
+ return deferred.promise();
+ }
+
+ if ( snapshot.snapshotTitle && snapshot.snapshotTitle.val() && 'publish' !== status ) {
+ requestData.title = snapshot.editControlSettings( 'title' ).get();
+ }
+
+ if ( ! _.isEmpty( snapshot.editContainer ) && snapshot.isFutureDate() && 'publish' !== status ) {
+ inputDate = snapshot.getDateFromInputs();
+ requestData.date = snapshot.formatDate( inputDate );
+ }
+
+ if ( 'future' === status ) {
+ if ( requestData.date ) {
+ request = snapshot.sendUpdateSnapshotRequest( requestData );
+ }
+ } else {
+ request = snapshot.sendUpdateSnapshotRequest( requestData );
+ }
+
+ return request ? request : deferred.promise();
+ },
+
+ /**
+ * Make the AJAX request to update/save a snapshot.
+ *
+ * @param {object} options Options.
+ * @param {string} options.status The post status for the snapshot.
+ * @return {object} request.
+ */
+ sendUpdateSnapshotRequest: function sendUpdateSnapshotRequest( options ) {
+ var snapshot = this,
+ request, data, isPublishStatus;
+
+ data = _.extend(
+ {
+ status: 'draft'
+ },
+ options
+ );
+
+ api.state( 'snapshot-saved' ).set( false );
+ snapshot.statusButton.disable( true );
+ snapshot.spinner.addClass( 'is-active' );
+
+ request = api.previewer.save( data );
+
+ isPublishStatus = 'publish' === data.status;
+
+ request.always( function( response ) {
+ snapshot.spinner.removeClass( 'is-active' );
+ if ( response.edit_link ) {
+ snapshot.data.editLink = response.edit_link;
+ }
+ if ( response.publish_date ) {
+ snapshot.data.publishDate = response.publish_date;
+ }
+ if ( response.title ) {
+ snapshot.data.title = response.title;
+ }
+
+ snapshot.data.dirty = false;
+ } );
+
+ request.done( function( response ) {
+ var url = api.previewer.previewUrl(),
+ customizeUrl = window.location.href,
+ savedDelay = 400;
+
+ /***
+ * Delay because api.Posts.updateSettingsQuietly updates the settings after save, which triggers
+ * api change causing the publish button to get enabled again.
+ */
+ _.delay( function() {
+ api.state( 'snapshot-saved' ).set( true );
+ if ( 'pending' === data.status ) {
+ api.state( 'snapshot-submitted' ).set( true );
+ }
+ }, savedDelay );
+
+ api.state( 'snapshot-exists' ).set( ! isPublishStatus );
+
+ snapshot.statusButton.disableSelect.set( isPublishStatus );
+ snapshot.statusButton.disbleButton.set( true );
+ snapshot.snapshotExpandButton.toggle( ! isPublishStatus );
+ snapshot.previewLink.toggle( ! isPublishStatus );
+
+ if ( isPublishStatus ) {
+ snapshot.removeParamFromClose( 'customize_changeset_uuid' );
+ }
+
+ snapshot.statusButton.updateButtonText( 'alt-text' );
+
+ // Trigger an event for plugins to use.
+ api.trigger( 'customize-snapshots-update', {
+ previewUrl: url,
+ customizeUrl: customizeUrl,
+ uuid: snapshot.data.uuid,
+ response: response
+ } );
+ } );
+
+ request.fail( function( response ) {
+ var id = '#snapshot-dialog-error',
+ snapshotDialogShareError = wp.template( 'snapshot-dialog-error' ),
+ messages = snapshot.data.i18n.errorMsg,
+ invalidityCount = 0,
+ dialogElement;
+
+ snapshot.statusButton.disableSelect.set( false );
+ snapshot.statusButton.disbleButton.set( false );
+
+ if ( response.setting_validities ) {
+ invalidityCount = _.size( response.setting_validities, function( validity ) {
+ return true !== validity;
+ } );
+ }
+
+ /*
+ * Short-circuit if there are setting validation errors, since the error messages
+ * will be displayed with the controls themselves. Eventually, once we have
+ * a global notification area in the Customizer, we can eliminate this
+ * short-circuit and instead display the messages in there.
+ * See https://core.trac.wordpress.org/ticket/35210
+ */
+ if ( invalidityCount > 0 ) {
+ return;
+ }
+
+ if ( response.errors ) {
+ messages += ' ' + _.pluck( response.errors, 'message' ).join( ' ' );
+ }
+
+ // Insert the snapshot dialog error template.
+ dialogElement = $( id );
+ if ( ! dialogElement.length ) {
+ dialogElement = $( snapshotDialogShareError( {
+ title: snapshot.data.i18n.errorTitle,
+ message: messages
+ } ) );
+ $( 'body' ).append( dialogElement );
+ }
+
+ // Open the dialog.
+ $( id ).dialog( {
+ autoOpen: true,
+ modal: true
+ } );
+ } );
+
+ return request;
+ },
+
+ /**
+ * Create the snapshot buttons.
+ *
+ * @return {void}
+ */
+ addButtons: function addButtons() {
+ var snapshot = this, disableButton = true, disableSelectButton = true,
+ setPreviewLinkHref, currentTheme, savedPreviewingTheme, themeNotActiveOrSaved;
+
+ snapshot.spinner = $( '#customize-header-actions' ).find( '.spinner' );
+ snapshot.publishButton = $( '#save' );
+
+ snapshot.publishButton.addClass( 'hidden' );
+ snapshot.statusButton = snapshot.addStatusButton();
+
+ if ( api.state( 'changesetStatus' ).get() ) {
+ disableSelectButton = false;
+ if ( 'auto-draft' === api.state( 'changesetStatus' ).get() ) {
+ disableButton = false;
+ } else {
+ snapshot.statusButton.updateButtonText( 'alt-text' );
+ }
+ }
+
+ currentTheme = api.settings.theme.stylesheet; // Or previewing theme.
+ savedPreviewingTheme = snapshot.data.previewingTheme;
+ themeNotActiveOrSaved = ! api.state( 'activated' ).get() && ! savedPreviewingTheme;
+ snapshot.isNotSavedPreviewingTheme = savedPreviewingTheme && savedPreviewingTheme !== currentTheme;
+
+ if ( themeNotActiveOrSaved || snapshot.isNotSavedPreviewingTheme ) {
+ disableButton = false;
+ disableSelectButton = false;
+ }
+
+ snapshot.statusButton.disbleButton.set( disableButton );
+ snapshot.statusButton.disableSelect.set( disableSelectButton );
+
+ // Preview link.
+ snapshot.previewLink = $( $.trim( wp.template( 'snapshot-preview-link' )() ) );
+ snapshot.previewLink.toggle( api.state( 'snapshot-saved' ).get() );
+ snapshot.previewLink.attr( 'target', snapshot.data.uuid );
+ setPreviewLinkHref = _.debounce( function() {
+ var queryVars;
+ if ( api.state( 'snapshot-exists' ).get() ) {
+ snapshot.previewLink.attr( 'href', snapshot.getSnapshotFrontendPreviewUrl() );
+ } else {
+ snapshot.previewLink.attr( 'href', snapshot.frontendPreviewUrl.get() );
+ }
+
+ // Add the customize_theme param to the frontend URL if the theme is not active.
+ if ( ! api.state( 'activated' ).get() ) {
+ queryVars = snapshot.parseQueryString( snapshot.previewLink.prop( 'search' ).substr( 1 ) );
+ queryVars.customize_theme = api.settings.theme.stylesheet;
+ snapshot.previewLink.prop( 'search', $.param( queryVars ) );
+ }
+ } );
+ snapshot.frontendPreviewUrl.bind( setPreviewLinkHref );
+ setPreviewLinkHref();
+ api.state.bind( 'change', setPreviewLinkHref );
+ api.bind( 'saved', setPreviewLinkHref );
+ snapshot.statusButton.container.after( snapshot.previewLink );
+ api.state( 'snapshot-saved' ).bind( function( saved ) {
+ snapshot.previewLink.toggle( saved );
+ } );
+
+ // Edit button.
+ snapshot.snapshotExpandButton = $( $.trim( wp.template( 'snapshot-expand-button' )( {} ) ) );
+ snapshot.statusButton.container.after( snapshot.snapshotExpandButton );
+
+ if ( ! snapshot.data.editLink ) {
+ snapshot.snapshotExpandButton.hide();
+ snapshot.previewLink.hide();
+ }
+
+ api.state( 'change', function() {
+ snapshot.snapshotExpandButton.toggle( api.state( 'snapshot-saved' ).get() && api.state( 'snapshot-exists' ).get() );
+ } );
+
+ api.state( 'snapshot-exists' ).bind( function( exist ) {
+ snapshot.snapshotExpandButton.toggle( exist );
+ snapshot.previewLink.toggle( exist );
+ } );
+
+ api.bind( 'change', function() {
+ if ( api.state( 'snapshot-saved' ).get() ) {
+ snapshot.statusButton.disable( false );
+ if ( snapshot.statusButton.button.data( 'confirm-text' ) !== snapshot.statusButton.buttonText.get() ) {
+ snapshot.statusButton.updateButtonText( 'button-text' );
+ }
+ if ( snapshot.submitButton ) {
+ snapshot.submitButton.prop( 'disabled', false );
+ }
+ if ( snapshot.saveButton ) {
+ snapshot.saveButton.prop( 'disabled', false );
+ }
+ api.state( 'snapshot-saved' ).set( false );
+ }
+ } );
+
+ if ( ! snapshot.data.currentUserCanPublish ) {
+ snapshot.addSubmitButton();
+ snapshot.addSaveButton();
+ }
+ },
+
+ /**
+ * Adds Submit Button when user does not have 'customize_publish' permission.
+ *
+ * @return {void}
+ */
+ addSubmitButton: function() {
+ var snapshot = this, disableSubmitButton;
+
+ disableSubmitButton = 'pending' === snapshot.data.postStatus || ! api.state( 'snapshot-exists' ).get();
+
+ if ( snapshot.statusButton ) {
+ snapshot.statusButton.container.hide();
+ } else {
+ snapshot.publishButton.hide();
+ }
+
+ snapshot.submitButton = $( $.trim( wp.template( 'snapshot-submit' )( {
+ buttonText: snapshot.data.i18n.submit
+ } ) ) );
+
+ snapshot.submitButton.prop( 'disabled', disableSubmitButton );
+ snapshot.submitButton.insertBefore( snapshot.publishButton );
+ api.state( 'snapshot-submitted' ).bind( function( submitted ) {
+ snapshot.submitButton.prop( 'disabled', submitted );
+ } );
+
+ snapshot.submitButton.on( 'click', function( event ) {
+ event.preventDefault();
+ snapshot.submitButton.prop( 'disabled', true );
+ if ( snapshot.saveButton ) {
+ snapshot.saveButton.prop( 'disabled', true );
+ }
+ snapshot.updateSnapshot( 'pending' ).fail( function() {
+ snapshot.submitButton.prop( 'disabled', false );
+ } );
+ } );
+
+ snapshot.editControlSettings.bind( 'change', function() {
+ if ( api.state( 'snapshot-saved' ).get() ) {
+ snapshot.submitButton.prop( 'disabled', false );
+ }
+ } );
+ },
+
+ /**
+ * Adds Save Button when user does not have 'customize_publish' permission.
+ *
+ * @return {void}
+ */
+ addSaveButton: function() {
+ var snapshot = this, disableSaveButton, isSaved;
+
+ isSaved = _.contains( [ 'future', 'pending', 'draft' ], api.state( 'changesetStatus' ).get() );
+ disableSaveButton = isSaved || ! api.state( 'snapshot-exists' ).get();
+
+ snapshot.saveButton = $( $.trim( wp.template( 'snapshot-save' )( {
+ buttonText: isSaved ? snapshot.data.i18n.updateButton : snapshot.data.i18n.saveButton
+ } ) ) );
+
+ snapshot.saveButton.prop( 'disabled', disableSaveButton );
+ snapshot.saveButton.insertBefore( snapshot.publishButton );
+
+ api.state( 'snapshot-submitted' ).bind( function( submitted ) {
+ if ( submitted ) {
+ snapshot.saveButton.prop( 'disabled', true );
+ }
+ } );
+
+ snapshot.saveButton.on( 'click', function( event ) {
+ event.preventDefault();
+ snapshot.saveButton.prop( 'disabled', true );
+ snapshot.submitButton.prop( 'disabled', true );
+ snapshot.updateSnapshot( 'draft' ).done( function() {
+ snapshot.saveButton.prop( 'disabled', true );
+ snapshot.submitButton.prop( 'disabled', false );
+ snapshot.saveButton.text( snapshot.data.i18n.updateButton );
+ } ).fail( function() {
+ snapshot.saveButton.prop( 'disabled', false );
+ snapshot.submitButton.prop( 'disabled', false );
+ } );
+ } );
+
+ snapshot.editControlSettings.bind( 'change', function() {
+ if ( api.state( 'snapshot-saved' ).get() ) {
+ snapshot.saveButton.prop( 'disabled', false );
+ }
+ } );
+ },
+
+ /**
+ * Renders snapshot schedule and handles it's events.
+ *
+ * @returns {void}
+ */
+ editSnapshotUI: function editSnapshotUI() {
+ var snapshot = this, sliceBegin = 0,
+ sliceEnd = -2, updateUI, toggleDateNotification;
+
+ snapshot.snapshotEditContainerDisplayed = new api.Value( false );
+
+ updateUI = function() {
+ snapshot.populateSetting();
+ };
+
+ // Inject the UI.
+ if ( _.isEmpty( snapshot.editContainer ) ) {
+ if ( '0000-00-00 00:00:00' === snapshot.data.publishDate ) {
+ snapshot.data.publishDate = snapshot.getCurrentTime();
+ }
+
+ // Normalize date with secs set as zeros removed.
+ snapshot.data.publishDate = snapshot.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
+
+ // Extend the snapshots data object and add the parsed datetime strings.
+ snapshot.data = _.extend( snapshot.data, snapshot.parseDateTime( snapshot.data.publishDate ) );
+
+ // Add the template to the DOM.
+ snapshot.editContainer = $( $.trim( wp.template( 'snapshot-edit-container' )( snapshot.data ) ) );
+ snapshot.editContainer.hide().appendTo( $( '#customize-header-actions' ) );
+ snapshot.dateNotification = snapshot.editContainer.find( '.snapshot-future-date-notification' );
+ snapshot.countdown = snapshot.editContainer.find( '.snapshot-scheduled-countdown' );
+ snapshot.dateControl = snapshot.editContainer.find( '.snapshot-control-date' );
+
+ if ( snapshot.data.currentUserCanPublish ) {
+
+ // Store the date inputs.
+ snapshot.schedule.inputs = snapshot.editContainer.find( '.date-input' );
+
+ snapshot.schedule.inputs.on( 'input', updateUI );
+
+ snapshot.schedule.inputs.on( 'blur', function() {
+ snapshot.populateInputs();
+ updateUI();
+ } );
+
+ snapshot.updateCountdown();
+
+ snapshot.editContainer.find( '.reset-time a' ).on( 'click', function( event ) {
+ event.preventDefault();
+ snapshot.updateSnapshotEditControls();
+ } );
+ }
+
+ if ( snapshot.statusButton && 'future' !== snapshot.statusButton.value.get() ) {
+ snapshot.countdown.hide();
+ }
+
+ snapshot.snapshotTitle = snapshot.editContainer.find( '#snapshot-title' );
+ snapshot.snapshotTitle.on( 'input', updateUI );
+ }
+
+ toggleDateNotification = function() {
+ if ( ! _.isEmpty( snapshot.dateNotification ) ) {
+ snapshot.dateNotification.toggle( ! snapshot.isFutureDate() );
+ }
+ };
+
+ // Set up toggling of the schedule container.
+ snapshot.snapshotEditContainerDisplayed.bind( function( isDisplayed ) {
+
+ if ( snapshot.statusButton ) {
+ snapshot.dateControl.toggle( 'future' === snapshot.statusButton.value.get() );
+ }
+
+ if ( isDisplayed ) {
+ snapshot.editContainer.stop().slideDown( 'fast' ).attr( 'aria-expanded', 'true' );
+ snapshot.snapshotExpandButton.attr( 'aria-pressed', 'true' );
+ snapshot.snapshotExpandButton.prop( 'title', snapshot.data.i18n.collapseSnapshotScheduling );
+ toggleDateNotification();
+ } else {
+ snapshot.editContainer.stop().slideUp( 'fast' ).attr( 'aria-expanded', 'false' );
+ snapshot.snapshotExpandButton.attr( 'aria-pressed', 'false' );
+ snapshot.snapshotExpandButton.prop( 'title', snapshot.data.i18n.expandSnapshotScheduling );
+ }
+ } );
+
+ snapshot.editControlSettings( 'date' ).bind( function() {
+ toggleDateNotification();
+ } );
+
+ // Toggle schedule container when clicking the button.
+ snapshot.snapshotExpandButton.on( 'click', function() {
+ snapshot.snapshotEditContainerDisplayed.set( ! snapshot.snapshotEditContainerDisplayed.get() );
+ } );
+
+ // Collapse the schedule container when Esc is pressed while the button is focused.
+ snapshot.snapshotExpandButton.on( 'keydown', function( event ) {
+ if ( escKeyCode === event.which && snapshot.snapshotEditContainerDisplayed.get() ) {
+ event.stopPropagation();
+ event.preventDefault();
+ snapshot.snapshotEditContainerDisplayed.set( false );
+ }
+ } );
+
+ // Collapse the schedule container when Esc is pressed inside of the schedule container.
+ snapshot.editContainer.on( 'keydown', function( event ) {
+ if ( escKeyCode === event.which && snapshot.snapshotEditContainerDisplayed.get() ) {
+ event.stopPropagation();
+ event.preventDefault();
+ snapshot.snapshotEditContainerDisplayed.set( false );
+ snapshot.snapshotExpandButton.focus();
+ }
+ } );
+
+ // Collapse the schedule container interacting outside the schedule container.
+ $( 'body' ).on( 'mousedown', function( event ) {
+ var isDisplayed = snapshot.snapshotEditContainerDisplayed.get(),
+ isTargetEditContainer = snapshot.editContainer.is( event.target ) || 0 !== snapshot.editContainer.has( event.target ).length,
+ isTargetExpandButton = snapshot.snapshotExpandButton.is( event.target );
+
+ if ( isDisplayed && ! isTargetEditContainer && ! isTargetExpandButton ) {
+ snapshot.snapshotEditContainerDisplayed.set( false );
+ }
+ } );
+
+ snapshot.snapshotEditContainerDisplayed.set( false );
+
+ api.state( 'snapshot-saved' ).bind( function( saved ) {
+ if ( saved && ! snapshot.dirtyEditControlValues ) {
+ snapshot.updateSnapshotEditControls();
+ }
+ } );
+
+ api.bind( 'change', function() {
+ snapshot.data.dirty = true;
+ snapshot.editContainer.find( 'a.snapshot-edit-link' ).hide();
+ } );
+
+ api.state( 'snapshot-exists' ).bind( function( exists ) {
+ if ( exists && ! _.isEmpty( snapshot.editContainer ) ) {
+ snapshot.updateSnapshotEditControls();
+ } else {
+ snapshot.snapshotEditContainerDisplayed.set( false );
+ }
+ } );
+
+ if ( snapshot.statusButton ) {
+ snapshot.updateSnapshotEditControls();
+ }
+
+ snapshot.autoSaveEditBox();
+ },
+
+ /**
+ * Auto save the edit box values.
+ *
+ * @return {void}
+ */
+ autoSaveEditBox: function() {
+ var snapshot = this, update,
+ delay = 2000, status, isFutureDateAndStatus;
+
+ snapshot.updatePending = false;
+ snapshot.dirtyEditControlValues = false;
+
+ update = _.debounce( function() {
+ status = snapshot.statusButton.value.get();
+ isFutureDateAndStatus = 'future' === status && ! snapshot.isFutureDate();
+ if ( 'publish' === status || isFutureDateAndStatus ) {
+ snapshot.updatePending = false;
+ return;
+ }
+ snapshot.updatePending = true;
+ snapshot.editBoxAutoSaveTriggered = true;
+ snapshot.dirtyEditControlValues = false;
+ snapshot.updateSnapshot( status ).done( function() {
+ snapshot.updatePending = snapshot.dirtyEditControlValues;
+ if ( ! snapshot.updatePending ) {
+ snapshot.updateSnapshotEditControls();
+ } else if ( snapshot.dirtyEditControlValues ) {
+ update();
+ }
+ snapshot.dirtyEditControlValues = false;
+ } ).fail( function() {
+ snapshot.updatePending = false;
+ snapshot.dirtyEditControlValues = true;
+ } );
+ }, delay );
+
+ snapshot.editControlSettings( 'title' ).bind( function() {
+ snapshot.dirtyEditControlValues = true;
+ if ( ! snapshot.updatePending ) {
+ update();
+ }
+ } );
+
+ snapshot.editControlSettings( 'date' ).bind( function() {
+ if ( snapshot.isFutureDate() ) {
+ snapshot.dirtyEditControlValues = true;
+ if ( ! snapshot.updatePending ) {
+ update();
+ }
+ }
+ } );
+
+ $( window ).on( 'beforeunload.customize-confirm', function() {
+ if ( snapshot.updatePending || snapshot.dirtyEditControlValues ) {
+ return snapshot.data.i18n.aysMsg;
+ }
+ return undefined;
+ } );
+
+ // @todo Show loader and disable button while auto saving.
+
+ api.bind( 'changeset-saved', function() {
+ if ( 'auto-draft' !== api.state( 'changesetStatus' ).get() ) {
+ api.state( 'saved' ).set( true ); // Suppress the AYS dialog.
+ }
+ });
+ },
+
+ /**
+ * Get the preview URL with the snapshot UUID attached.
+ *
+ * @returns {string} URL.
+ */
+ getSnapshotFrontendPreviewUrl: function getSnapshotFrontendPreviewUrl() {
+ var snapshot = this, a = document.createElement( 'a' );
+ a.href = snapshot.frontendPreviewUrl.get();
+ if ( a.search ) {
+ a.search += '&';
+ }
+ a.search += snapshot.uuidParam + '=' + snapshot.data.uuid;
+ return a.href;
+ },
+
+ /**
+ * Updates snapshot schedule with `snapshot.data`.
+ *
+ * @return {void}
+ */
+ updateSnapshotEditControls: function updateSnapshotEditControls() {
+ var snapshot = this,
+ parsed,
+ status,
+ sliceBegin = 0,
+ sliceEnd = -2;
+
+ if ( _.isEmpty( snapshot.editContainer ) ) {
+ return;
+ }
+
+ status = api.state( 'changesetStatus' ).get();
+
+ if ( snapshot.data.currentUserCanPublish ) {
+ if ( '0000-00-00 00:00:00' === snapshot.data.publishDate || ! status || 'auto-draft' === status ) {
+ snapshot.data.publishDate = snapshot.getCurrentTime();
+ }
+
+ // Normalize date with seconds removed.
+ snapshot.data.publishDate = snapshot.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
+ parsed = snapshot.parseDateTime( snapshot.data.publishDate );
+
+ // Update date controls.
+ snapshot.schedule.inputs.each( function() {
+ var input = $( this ),
+ fieldName = input.data( 'date-input' );
+ $( this ).val( parsed[ fieldName ] );
+ } );
+ }
+
+ snapshot.editContainer.find( 'a.snapshot-edit-link' )
+ .attr( 'href', snapshot.data.editLink )
+ .show();
+ if ( ! _.isEmpty( snapshot.data.title ) ) {
+ snapshot.snapshotTitle.val( snapshot.data.title );
+ }
+ snapshot.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.
+ */
+ updateCountdown: function updateCountdown() {
+ var snapshot = this,
+ countdownTemplate = wp.template( 'snapshot-scheduled-countdown' ),
+ dateTimeFromInput = snapshot.getDateFromInputs(),
+ millisecondsDivider = 1000,
+ remainingTime;
+
+ if ( ! dateTimeFromInput ) {
+ return false;
+ }
+
+ remainingTime = dateTimeFromInput.valueOf();
+ remainingTime -= snapshot.dateValueOf( snapshot.getCurrentTime() );
+ remainingTime = Math.ceil( remainingTime / millisecondsDivider );
+
+ if ( 0 < remainingTime ) {
+ snapshot.countdown.text( countdownTemplate( {
+ remainingTime: remainingTime
+ } ) );
+ snapshot.countdown.show();
+ } else {
+ snapshot.countdown.hide();
+ }
+
+ return true;
+ },
+
+ /**
+ * Get date from inputs.
+ *
+ * @returns {Date|null} Date created from inputs or null if invalid date.
+ */
+ getDateFromInputs: function getDateFromInputs() {
+ var snapshot = this,
+ template = snapshot.editContainer,
+ 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.
+ */
+ 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.
+ */
+ formatDate: function formatDate( date ) {
+ var formattedDate,
+ yearLength = 4,
+ nonYearLength = 2,
+ monthOffset = 1;
+
+ formattedDate = ( '0000' + String( date.getFullYear() ) ).substr( -yearLength, yearLength );
+ formattedDate += '-' + ( '00' + String( date.getMonth() + monthOffset ) ).substr( -nonYearLength, nonYearLength );
+ formattedDate += '-' + ( '00' + String( date.getDate() ) ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ' ' + ( '00' + String( date.getHours() ) ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ':' + ( '00' + String( date.getMinutes() ) ).substr( -nonYearLength, nonYearLength );
+ formattedDate += ':' + ( '00' + String( 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.
+ */
+ populateInputs: function populateInputs() {
+ var snapshot = this, parsed;
+
+ if ( snapshot.schedule.inputs.is( ':focus' ) || '0000-00-00 00:00:00' === snapshot.data.publishDate ) {
+ return false;
+ }
+
+ parsed = snapshot.parseDateTime( snapshot.data.publishDate );
+ if ( ! parsed ) {
+ return false;
+ }
+
+ snapshot.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 {void}
+ */
+ populateSetting: function populateSetting() {
+ var snapshot = this,
+ date = snapshot.getDateFromInputs(),
+ scheduled;
+
+ snapshot.editControlSettings( 'title' ).set( snapshot.snapshotTitle.val() );
+
+ if ( ! date || ! snapshot.data.currentUserCanPublish ) {
+ return;
+ }
+
+ date.setSeconds( 0 );
+ scheduled = snapshot.formatDate( date ) !== snapshot.data.publishDate;
+ snapshot.editControlSettings( 'date' ).set( snapshot.formatDate( date ) );
+
+ if ( 'future' === snapshot.statusButton.value.get() ) {
+ snapshot.updateCountdown();
+ }
+
+ snapshot.editContainer.find( '.reset-time' ).toggle( scheduled );
+ },
+
+ /**
+ * Check if the schedule date is in the future.
+ *
+ * @returns {boolean} True if future date.
+ */
+ isFutureDate: function isFutureDate() {
+ var snapshot = this,
+ date = snapshot.getDateFromInputs(),
+ millisecondsDivider = 1000,
+ remainingTime;
+
+ if ( ! date ) {
+ return false;
+ }
+
+ remainingTime = snapshot.dateValueOf( date );
+ remainingTime -= snapshot.dateValueOf( snapshot.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.
+ */
+ getCurrentTime: function getCurrentTime() {
+ var snapshot = this, currentDate, currentTimestamp, timestampDifferential;
+ currentTimestamp = ( new Date() ).valueOf();
+ currentDate = snapshot.parsePostDate( snapshot.data.initialServerDate );
+ timestampDifferential = currentTimestamp - snapshot.data.initialClientTimestamp;
+ timestampDifferential += snapshot.data.initialClientTimestamp - snapshot.data.initialServerTimestamp;
+ currentDate.setTime( currentDate.getTime() + timestampDifferential );
+ return snapshot.formatDate( currentDate );
+ },
+
+ /**
+ * Parse post date string in YYYY-MM-DD HH:MM:SS format (local timezone).
+ *
+ * @param {string} postDate Post date string.
+ * @returns {Date} Parsed date.
+ */
+ parsePostDate: function parsePostDate( postDate ) {
+ var dateParts = _.map( postDate.split( /\D/ ), function( datePart ) {
+ return parseInt( datePart, 10 );
+ } );
+ return new Date( dateParts[0], dateParts[1] - 1, dateParts[2], dateParts[3], dateParts[4], dateParts[5] ); // eslint-disable-line no-magic-numbers
+ },
+
+ /**
+ * 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.
+ */
+ dateValueOf: function dateValueOf( 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();
+ },
+
+ /**
+ * Amend the preview query so we can update the snapshot during `changeset_save`.
+ *
+ * @return {void}
+ */
+ extendPreviewerQuery: function extendPreviewerQuery() {
+ var snapshot = this, originalQuery = api.previewer.query;
+
+ api.previewer.query = function() {
+ var retval = originalQuery.apply( this, arguments );
+
+ if ( ! _.contains( [ 'future', 'pending', 'draft' ], snapshot.statusButton.value.get() ) ) {
+ return retval;
+ }
+
+ retval.customizer_state_query_vars = JSON.stringify( snapshot.getStateQueryVars() );
+
+ if ( snapshot.editControlSettings( 'title' ).get() ) {
+ retval.customize_changeset_title = snapshot.editControlSettings( 'title' ).get();
+ }
+ if ( snapshot.editControlSettings( 'date' ).get() && snapshot.isFutureDate() ) {
+ retval.customize_changeset_date = snapshot.editControlSettings( 'date' ).get();
+ }
+ return retval;
+ };
+ },
+
+ /**
+ * Add status button.
+ *
+ * @return {object} status button.
+ */
+ addStatusButton: function addStatusButton() {
+ var snapshot = this, selectMenuButton, statusButton, selectedOption, buttonText, changesetStatus, selectedStatus;
+ changesetStatus = api.state( 'changesetStatus' ).get();
+ statusButton = {};
+
+ selectedStatus = changesetStatus && 'auto-draft' !== changesetStatus ? changesetStatus : 'publish';
+
+ statusButton.value = new api.Value( selectedStatus );
+ statusButton.disbleButton = new api.Value();
+ statusButton.disableSelect = new api.Value();
+ statusButton.buttonText = new api.Value();
+ statusButton.needConfirm = false;
+
+ statusButton.container = $( $.trim( wp.template( 'snapshot-status-button' )({
+ selected: selectedStatus
+ }) ) );
+ statusButton.button = statusButton.container.find( '.snapshot-status-button-overlay' );
+ statusButton.select = statusButton.container.find( 'select' );
+ statusButton.select.selectmenu({
+ width: 'auto',
+ icons: {
+ button: 'dashicons dashicons-arrow-down'
+ },
+ change: function( event, ui ) {
+ statusButton.value.set( ui.item.value );
+ },
+ select: function() {
+ if ( statusButton.hiddenButton ) {
+ statusButton.hiddenButton.text( statusButton.buttonText.get() );
+ }
+ }
+ });
+
+ selectMenuButton = statusButton.container.find( '.ui-selectmenu-button' );
+ statusButton.hiddenButton = selectMenuButton.find( '.ui-selectmenu-text' );
+ statusButton.hiddenButton.addClass( 'button button-primary' );
+
+ statusButton.dropDown = selectMenuButton.find( '.ui-icon' );
+ statusButton.dropDown.addClass( 'button button-primary' );
+
+ statusButton.updateButtonText = function( dataAttr ) {
+ buttonText = statusButton.button.data( dataAttr );
+ statusButton.button.text( buttonText );
+ statusButton.hiddenButton.text( buttonText );
+ statusButton.buttonText.set( buttonText );
+ };
+
+ statusButton.value.bind( function( status ) {
+ selectedOption = statusButton.select.find( 'option:selected' );
+ statusButton.button.data( 'alt-text', selectedOption.data( 'alt-text' ) );
+ statusButton.button.data( 'button-text', selectedOption.text() );
+ statusButton.updateButtonText( 'button-text' );
+
+ if ( 'publish' === status ) {
+ snapshot.snapshotExpandButton.hide();
+ statusButton.button.data( 'confirm-text', selectedOption.data( 'confirm-text' ) );
+ statusButton.button.data( 'publish-text', selectedOption.data( 'publish-text' ) );
+ statusButton.needConfirm = true;
+ }
+
+ if ( 'future' === status ) {
+ snapshot.snapshotEditContainerDisplayed.set( true );
+ snapshot.snapshotExpandButton.show();
+ if ( snapshot.isFutureDate() ) {
+ snapshot.countdown.show();
+ snapshot.updateSnapshot( status );
+ }
+ } else {
+ snapshot.updateSnapshot( status );
+ snapshot.snapshotEditContainerDisplayed.set( false );
+ snapshot.countdown.hide();
+ }
+ } );
+
+ statusButton.disbleButton.bind( function( disabled ) {
+ statusButton.button.prop( 'disabled', disabled );
+ } );
+
+ statusButton.disableSelect.bind( function( disabled ) {
+ statusButton.select.selectmenu( disabled ? 'disable' : 'enable' );
+ statusButton.dropDown.toggleClass( 'disabled', disabled );
+ } );
+
+ statusButton.disable = function( disable ) {
+ statusButton.disableSelect.set( disable );
+ statusButton.disbleButton.set( disable );
+ };
+
+ statusButton.button.on( 'click', function( event ) {
+ event.preventDefault();
+ snapshot.updateSnapshot( statusButton.value.get() );
+ } );
+
+ snapshot.publishButton.after( statusButton.container );
+
+ return statusButton;
+ },
+
+ /**
+ * Remove 'customize_changeset_status' if it is being auto saved for edit box to avoid revisions.
+ *
+ * @return {void}
+ */
+ prefilterAjax: function prefilterAjax() {
+ var snapshot = this, removeParam, isSameStatus;
+
+ if ( ! api.state.has( 'changesetStatus' ) ) {
+ return;
+ }
+
+ removeParam = function( queryString, parameter ) {
+ var pars = queryString.split( /[&;]/g );
+
+ _.each( pars, function( string, index ) {
+ if ( string && string.lastIndexOf( parameter, 0 ) !== -1 ) {
+ pars.splice( index, 1 );
+ }
+ } );
+
+ return pars.join( '&' );
+ };
+
+ $.ajaxPrefilter( function( options, originalOptions ) {
+ if ( ! originalOptions.data || ! snapshot.editBoxAutoSaveTriggered ) {
+ return;
+ }
+
+ isSameStatus = api.state( 'changesetStatus' ).get() === originalOptions.data.customize_changeset_status;
+ if ( 'customize_save' === originalOptions.data.action && options.data && originalOptions.data.customize_changeset_status && isSameStatus ) {
+ options.data = removeParam( options.data, 'customize_changeset_status' );
+ snapshot.editBoxAutoSaveTriggered = false;
+ }
+ } );
+ },
+
+ /**
+ * Remove a param from close button link.
+ *
+ * @param {string} targetParam param.
+ * @return {void}.
+ */
+ removeParamFromClose: function removeParamFromClose( targetParam ) {
+ var snapshot = this, closeButton, queryString, updatedParams;
+ closeButton = $( '.customize-controls-close' );
+ queryString = closeButton.prop( 'search' ).substr( 1 );
+
+ if ( ! queryString.length ) {
+ return;
+ }
+
+ updatedParams = snapshot.parseQueryString( queryString );
+ delete updatedParams[ targetParam ];
+ closeButton.prop( 'search', $.param( updatedParams ) );
+ },
+
+ /**
+ * Parse query string.
+ *
+ * @since 4.7.0
+ * @access public
+ *
+ * @param {string} queryString Query string.
+ * @returns {object} Parsed query string.
+ */
+ parseQueryString: api.utils.parseQueryString
+ } );
+})( wp.customize, jQuery );
diff --git a/js/customize-snapshots-frontend.js b/js/customize-snapshots-frontend.js
index 23ed8e09..b2b0e1df 100644
--- a/js/customize-snapshots-frontend.js
+++ b/js/customize-snapshots-frontend.js
@@ -11,7 +11,8 @@ var CustomizeSnapshotsFrontend = ( function( $ ) {
uuid: '',
l10n: {
restoreSessionPrompt: ''
- }
+ },
+ confirmationMsg: ''
}
};
@@ -30,6 +31,12 @@ var CustomizeSnapshotsFrontend = ( function( $ ) {
component.keepSessionAlive();
component.rememberSessionSnapshot();
component.handleExitSnapshotSessionLink();
+
+ if ( component.data.uuid ) {
+ $( document ).ready( function() {
+ component.setupPublishButton();
+ } );
+ }
};
/**
@@ -75,7 +82,8 @@ var CustomizeSnapshotsFrontend = ( function( $ ) {
* @returns {void}
*/
component.rememberSessionSnapshot = function rememberSessionSnapshot() {
- if ( ! component.hasSessionStorage || ! component.data.uuid ) {
+ var isCustomizerFramePreview = /(^|\?|&)customize_messenger_channel=/.test( location.search );
+ if ( ! component.hasSessionStorage || ! component.data.uuid || isCustomizerFramePreview ) {
return;
}
sessionStorage.setItem( 'customize_changeset_uuid', component.data.uuid );
@@ -97,6 +105,27 @@ var CustomizeSnapshotsFrontend = ( function( $ ) {
} );
};
+ /**
+ * Set up changesets frontend publish button in admin bar.
+ *
+ * @returns {void}
+ */
+ component.setupPublishButton = function setupPublishButton() {
+ var publishBtn = $( '#wp-admin-bar-publish-customize-changeset a' );
+
+ if ( ! publishBtn.length ) {
+ return;
+ }
+
+ publishBtn.click( function() {
+ if ( ! window.confirm( component.data.confirmationMsg ) ) { // eslint-disable-line no-alert
+ return false;
+ }
+ sessionStorage.removeItem( 'customize_changeset_uuid' );
+ return true;
+ } );
+ };
+
return component;
} )( jQuery );
diff --git a/js/customize-snapshots.js b/js/customize-snapshots.js
index ed72de95..918219fb 100644
--- a/js/customize-snapshots.js
+++ b/js/customize-snapshots.js
@@ -1,104 +1,110 @@
-/* global jQuery, wp, JSON, _customizeSnapshotsSettings */
-/* eslint no-magic-numbers: [ "error", { "ignore": [0,1,-1] } ], consistent-this: [ "error", "snapshot" ] */
+/* global wp, jQuery */
+/* eslint consistent-this: [ "error", "snapshot", "control" ] */
+/* eslint no-magic-numbers: ["error", { "ignore": [0, 1] }] */
(function( api, $ ) {
'use strict';
- var escKeyCode = 27;
-
api.Snapshots = api.Class.extend( {
data: {
- action: '',
- uuid: '',
- editLink: '',
+ inspectLink: '',
title: '',
- publishDate: '',
- postStatus: '',
- currentUserCanPublish: true,
- initialServerDate: '',
- initialServerTimestamp: 0,
- initialClientTimestamp: 0,
- previewingTheme: '',
- i18n: {},
- dirty: false
+ i18n: {
+ title: '',
+ savePending: '',
+ pendingSaved: '',
+ aysMsg: ''
+ }
},
- uuidParam: 'customize_changeset_uuid',
-
initialize: function initialize( snapshotsConfig ) {
var snapshot = this;
- snapshot.schedule = {};
-
if ( _.isObject( snapshotsConfig ) ) {
_.extend( snapshot.data, snapshotsConfig );
}
- // Set the initial client timestamp.
- snapshot.data.initialClientTimestamp = snapshot.dateValueOf();
-
api.bind( 'ready', function() {
- api.state.create( 'snapshot-exists', false );
- api.state.create( 'snapshot-saved', true );
- api.state.create( 'snapshot-submitted', true );
-
- snapshot.data.uuid = snapshot.data.uuid || api.settings.changeset.uuid;
- snapshot.data.title = snapshot.data.title || snapshot.data.uuid;
+ var saveBtn = $( '#save' );
- snapshot.editBoxAutoSaveTriggered = false;
+ snapshot.data.title = snapshot.data.title || api.settings.changeset.uuid;
+ api.state.create( 'changesetTitle', snapshot.data.title );
+ api.state.create( 'changesetInspectUrl', snapshot.data.inspectLink );
- if ( api.state.has( 'changesetStatus' ) && api.state( 'changesetStatus' ).get() ) {
- api.state( 'snapshot-exists' ).set( true );
- }
+ api.control( 'changeset_scheduled_date', snapshot.setupScheduledChangesetCountdown );
- snapshot.extendPreviewerQuery();
+ api.bind( 'save-request-params', function( data ) {
+ data.customizer_state_query_vars = JSON.stringify( snapshot.getStateQueryVars() );
+ data.customize_changeset_title = api.state( 'changesetTitle' );
+ } );
- snapshot.editControlSettings = new api.Values();
- snapshot.editControlSettings.create( 'title', snapshot.data.title );
- snapshot.editControlSettings.create( 'date', snapshot.data.publishDate );
+ api.state.bind( 'change', function() {
+ if ( api.state( 'activated' ).get() && 'pending' === api.state( 'selectedChangesetStatus' ).get() ) {
+ if ( api.state( 'saved' ).get() && api.state( 'selectedChangesetStatus' ).get() === api.state( 'changesetStatus' ).get() ) {
+ saveBtn.val( snapshot.data.i18n.pendingSaved );
+ } else {
+ saveBtn.val( snapshot.data.i18n.savePending );
+ }
+ }
+ } );
- api.bind( 'change', function() {
- api.state( 'snapshot-submitted' ).set( false );
+ api.section( 'publish_settings', function( section ) {
+ snapshot.addPendingToStatusControl();
+ snapshot.addTitleControl( section );
+ snapshot.addInspectChangesetControl( section );
} );
+ // For backward compat.
snapshot.frontendPreviewUrl = new api.Value( api.previewer.previewUrl.get() );
snapshot.frontendPreviewUrl.link( api.previewer.previewUrl );
- snapshot.isNotSavedPreviewingTheme = false;
-
- snapshot.addButtons();
- snapshot.editSnapshotUI();
- snapshot.prefilterAjax();
api.trigger( 'snapshots-ready', snapshot );
} );
api.bind( 'save', function( request ) {
+ request.done( function( response ) {
+ if ( response.edit_link ) {
+ api.state( 'changesetInspectUrl' ).set( response.edit_link );
+ }
+ if ( response.title ) {
+ api.state( 'changesetTitle' ).set( response.title );
+ }
- request.fail( function( response ) {
- var id = '#snapshot-dialog-error',
- snapshotDialogPublishError = wp.template( 'snapshot-dialog-error' );
+ // Trigger an event for plugins to use, for backward compat.
+ api.trigger( 'customize-snapshots-update', response );
+ } );
+ } );
+ },
- if ( response.responseText ) {
+ /**
+ * Add title control to publish settings section.
+ *
+ * @param {wp.customize.Section} section Publish settings section.
+ * @return {void}
+ */
+ addTitleControl: function( section ) {
+ var snapshot = this, titleControl;
- // Insert the dialog error template.
- if ( 0 === $( id ).length ) {
- $( 'body' ).append( snapshotDialogPublishError( {
- title: snapshot.data.i18n.publish,
- message: api.state( 'snapshot-exists' ).get() ? snapshot.data.i18n.permsMsg.update : snapshot.data.i18n.permsMsg.save
- } ) );
- }
+ titleControl = new api.Control( 'changeset_title', {
+ type: 'text',
+ label: snapshot.data.i18n.title,
+ section: section.id,
+ setting: api.state( 'changesetTitle' ),
+ priority: 31
+ } );
- snapshot.spinner.removeClass( 'is-active' );
+ api.control.add( titleControl );
- $( id ).dialog( {
- autoOpen: true,
- modal: true
- } );
- }
- } );
+ api.state( 'changesetTitle' ).bind( function() {
+ api.state( 'saved' ).set( false );
+ } );
- return request;
+ $( window ).on( 'beforeunload.customize-confirm', function() {
+ if ( ! api.state( 'saved' ).get() ) {
+ return snapshot.data.i18n.aysMsg;
+ }
+ return undefined;
} );
},
@@ -139,1090 +145,120 @@
},
/**
- * Update snapshot.
+ * Setup scheduled changeset countdown.
*
- * @param {string} status post status.
- * @returns {jQuery.promise} Request or promise.
- */
- updateSnapshot: function updateSnapshot( status ) {
- var snapshot = this, inputDate,
- deferred = new $.Deferred(),
- request,
- requestData = {
- status: status
- };
-
- if ( snapshot.statusButton && snapshot.statusButton.needConfirm ) {
- snapshot.statusButton.disbleButton.set( false );
- snapshot.statusButton.updateButtonText( 'confirm-text' );
- snapshot.statusButton.needConfirm = false;
- return deferred.promise();
- }
-
- if ( snapshot.snapshotTitle && snapshot.snapshotTitle.val() && 'publish' !== status ) {
- requestData.title = snapshot.editControlSettings( 'title' ).get();
- }
-
- if ( ! _.isEmpty( snapshot.editContainer ) && snapshot.isFutureDate() && 'publish' !== status ) {
- inputDate = snapshot.getDateFromInputs();
- requestData.date = snapshot.formatDate( inputDate );
- }
-
- if ( 'future' === status ) {
- if ( requestData.date ) {
- request = snapshot.sendUpdateSnapshotRequest( requestData );
- }
- } else {
- request = snapshot.sendUpdateSnapshotRequest( requestData );
- }
-
- return request ? request : deferred.promise();
- },
-
- /**
- * Make the AJAX request to update/save a snapshot.
- *
- * @param {object} options Options.
- * @param {string} options.status The post status for the snapshot.
- * @return {object} request.
+ * @param {wp.customize.Control} dateControl Changeset schedule date control.
+ * @return {void}
*/
- sendUpdateSnapshotRequest: function sendUpdateSnapshotRequest( options ) {
- var snapshot = this,
- request, data, isPublishStatus;
-
- data = _.extend(
- {
- status: 'draft'
- },
- options
- );
-
- api.state( 'snapshot-saved' ).set( false );
- snapshot.statusButton.disable( true );
- snapshot.spinner.addClass( 'is-active' );
-
- request = api.previewer.save( data );
-
- isPublishStatus = 'publish' === data.status;
+ setupScheduledChangesetCountdown: function( dateControl ) {
+ var template, countdownContainer, setNextChangesetUUID;
- request.always( function( response ) {
- snapshot.spinner.removeClass( 'is-active' );
- if ( response.edit_link ) {
- snapshot.data.editLink = response.edit_link;
- }
- if ( response.publish_date ) {
- snapshot.data.publishDate = response.publish_date;
- }
- if ( response.title ) {
- snapshot.data.title = response.title;
- }
-
- snapshot.data.dirty = false;
+ template = wp.template( 'snapshot-scheduled-countdown' );
+ countdownContainer = $( '
', {
+ 'class': 'snapshot-countdown-container hidden'
} );
- request.done( function( response ) {
- var url = api.previewer.previewUrl(),
- customizeUrl = window.location.href,
- savedDelay = 400;
+ setNextChangesetUUID = function( response ) {
+ api.state( 'changesetTitle' ).set( response.next_changeset_uuid );
+ api.state( 'saved' ).set( true );
+ api.unbind( 'saved', setNextChangesetUUID );
+ };
- /***
- * Delay because api.Posts.updateSettingsQuietly updates the settings after save, which triggers
- * api change causing the publish button to get enabled again.
- */
- _.delay( function() {
- api.state( 'snapshot-saved' ).set( true );
- if ( 'pending' === data.status ) {
- api.state( 'snapshot-submitted' ).set( true );
+ dateControl.deferred.embedded.done( function() {
+ dateControl.container.append( countdownContainer );
+ api.state( 'remainingTimeToPublish' ).bind( function( time ) {
+ if ( 0 === parseInt( time, 10 ) ) {
+ api.bind( 'saved', setNextChangesetUUID );
}
- }, savedDelay );
-
- api.state( 'snapshot-exists' ).set( ! isPublishStatus );
-
- snapshot.statusButton.disableSelect.set( isPublishStatus );
- snapshot.statusButton.disbleButton.set( true );
- snapshot.snapshotExpandButton.toggle( ! isPublishStatus );
- snapshot.previewLink.toggle( ! isPublishStatus );
-
- if ( isPublishStatus ) {
- snapshot.removeParamFromClose( 'customize_changeset_uuid' );
- }
-
- snapshot.statusButton.updateButtonText( 'alt-text' );
-
- // Trigger an event for plugins to use.
- api.trigger( 'customize-snapshots-update', {
- previewUrl: url,
- customizeUrl: customizeUrl,
- uuid: snapshot.data.uuid,
- response: response
- } );
- } );
-
- request.fail( function( response ) {
- var id = '#snapshot-dialog-error',
- snapshotDialogShareError = wp.template( 'snapshot-dialog-error' ),
- messages = snapshot.data.i18n.errorMsg,
- invalidityCount = 0,
- dialogElement;
-
- snapshot.statusButton.disableSelect.set( false );
- snapshot.statusButton.disbleButton.set( false );
-
- if ( response.setting_validities ) {
- invalidityCount = _.size( response.setting_validities, function( validity ) {
- return true !== validity;
- } );
- }
-
- /*
- * Short-circuit if there are setting validation errors, since the error messages
- * will be displayed with the controls themselves. Eventually, once we have
- * a global notification area in the Customizer, we can eliminate this
- * short-circuit and instead display the messages in there.
- * See https://core.trac.wordpress.org/ticket/35210
- */
- if ( invalidityCount > 0 ) {
- return;
- }
-
- if ( response.errors ) {
- messages += ' ' + _.pluck( response.errors, 'message' ).join( ' ' );
- }
-
- // Insert the snapshot dialog error template.
- dialogElement = $( id );
- if ( ! dialogElement.length ) {
- dialogElement = $( snapshotDialogShareError( {
- title: snapshot.data.i18n.errorTitle,
- message: messages
+ countdownContainer.removeClass( 'hidden' ).html( template( {
+ remainingTime: time
} ) );
- $( 'body' ).append( dialogElement );
- }
-
- // Open the dialog.
- $( id ).dialog( {
- autoOpen: true,
- modal: true
} );
- } );
-
- return request;
- },
-
- /**
- * Create the snapshot buttons.
- *
- * @return {void}
- */
- addButtons: function addButtons() {
- var snapshot = this, disableButton = true, disableSelectButton = true,
- setPreviewLinkHref, currentTheme, savedPreviewingTheme, themeNotActiveOrSaved;
-
- snapshot.spinner = $( '#customize-header-actions' ).find( '.spinner' );
- snapshot.publishButton = $( '#save' );
-
- snapshot.publishButton.addClass( 'hidden' );
- snapshot.statusButton = snapshot.addStatusButton();
-
- if ( api.state( 'changesetStatus' ).get() ) {
- disableSelectButton = false;
- if ( 'auto-draft' === api.state( 'changesetStatus' ).get() ) {
- disableButton = false;
- } else {
- snapshot.statusButton.updateButtonText( 'alt-text' );
- }
- }
-
- currentTheme = api.settings.theme.stylesheet; // Or previewing theme.
- savedPreviewingTheme = snapshot.data.previewingTheme;
- themeNotActiveOrSaved = ! api.state( 'activated' ).get() && ! savedPreviewingTheme;
- snapshot.isNotSavedPreviewingTheme = savedPreviewingTheme && savedPreviewingTheme !== currentTheme;
-
- if ( themeNotActiveOrSaved || snapshot.isNotSavedPreviewingTheme ) {
- disableButton = false;
- disableSelectButton = false;
- }
-
- snapshot.statusButton.disbleButton.set( disableButton );
- snapshot.statusButton.disableSelect.set( disableSelectButton );
-
- // Preview link.
- snapshot.previewLink = $( $.trim( wp.template( 'snapshot-preview-link' )() ) );
- snapshot.previewLink.toggle( api.state( 'snapshot-saved' ).get() );
- snapshot.previewLink.attr( 'target', snapshot.data.uuid );
- setPreviewLinkHref = _.debounce( function() {
- var queryVars;
- if ( api.state( 'snapshot-exists' ).get() ) {
- snapshot.previewLink.attr( 'href', snapshot.getSnapshotFrontendPreviewUrl() );
- } else {
- snapshot.previewLink.attr( 'href', snapshot.frontendPreviewUrl.get() );
- }
-
- // Add the customize_theme param to the frontend URL if the theme is not active.
- if ( ! api.state( 'activated' ).get() ) {
- queryVars = snapshot.parseQueryString( snapshot.previewLink.prop( 'search' ).substr( 1 ) );
- queryVars.customize_theme = api.settings.theme.stylesheet;
- snapshot.previewLink.prop( 'search', $.param( queryVars ) );
- }
- } );
- snapshot.frontendPreviewUrl.bind( setPreviewLinkHref );
- setPreviewLinkHref();
- api.state.bind( 'change', setPreviewLinkHref );
- api.bind( 'saved', setPreviewLinkHref );
- snapshot.statusButton.container.after( snapshot.previewLink );
- api.state( 'snapshot-saved' ).bind( function( saved ) {
- snapshot.previewLink.toggle( saved );
- } );
-
- // Edit button.
- snapshot.snapshotExpandButton = $( $.trim( wp.template( 'snapshot-expand-button' )( {} ) ) );
- snapshot.statusButton.container.after( snapshot.snapshotExpandButton );
-
- if ( ! snapshot.data.editLink ) {
- snapshot.snapshotExpandButton.hide();
- snapshot.previewLink.hide();
- }
-
- api.state( 'change', function() {
- snapshot.snapshotExpandButton.toggle( api.state( 'snapshot-saved' ).get() && api.state( 'snapshot-exists' ).get() );
- } );
- api.state( 'snapshot-exists' ).bind( function( exist ) {
- snapshot.snapshotExpandButton.toggle( exist );
- snapshot.previewLink.toggle( exist );
- } );
-
- api.bind( 'change', function() {
- if ( api.state( 'snapshot-saved' ).get() ) {
- snapshot.statusButton.disable( false );
- if ( snapshot.statusButton.button.data( 'confirm-text' ) !== snapshot.statusButton.buttonText.get() ) {
- snapshot.statusButton.updateButtonText( 'button-text' );
- }
- if ( snapshot.submitButton ) {
- snapshot.submitButton.prop( 'disabled', false );
- }
- if ( snapshot.saveButton ) {
- snapshot.saveButton.prop( 'disabled', false );
+ api.state( 'changesetStatus' ).bind( function( status ) {
+ if ( 'future' !== status ) {
+ countdownContainer.addClass( 'hidden' );
}
- api.state( 'snapshot-saved' ).set( false );
- }
- } );
-
- if ( ! snapshot.data.currentUserCanPublish ) {
- snapshot.addSubmitButton();
- snapshot.addSaveButton();
- }
- },
-
- /**
- * Adds Submit Button when user does not have 'customize_publish' permission.
- *
- * @return {void}
- */
- addSubmitButton: function() {
- var snapshot = this, disableSubmitButton;
-
- disableSubmitButton = 'pending' === snapshot.data.postStatus || ! api.state( 'snapshot-exists' ).get();
-
- if ( snapshot.statusButton ) {
- snapshot.statusButton.container.hide();
- } else {
- snapshot.publishButton.hide();
- }
-
- snapshot.submitButton = $( $.trim( wp.template( 'snapshot-submit' )( {
- buttonText: snapshot.data.i18n.submit
- } ) ) );
-
- snapshot.submitButton.prop( 'disabled', disableSubmitButton );
- snapshot.submitButton.insertBefore( snapshot.publishButton );
- api.state( 'snapshot-submitted' ).bind( function( submitted ) {
- snapshot.submitButton.prop( 'disabled', submitted );
- } );
-
- snapshot.submitButton.on( 'click', function( event ) {
- event.preventDefault();
- snapshot.submitButton.prop( 'disabled', true );
- if ( snapshot.saveButton ) {
- snapshot.saveButton.prop( 'disabled', true );
- }
- snapshot.updateSnapshot( 'pending' ).fail( function() {
- snapshot.submitButton.prop( 'disabled', false );
} );
} );
-
- snapshot.editControlSettings.bind( 'change', function() {
- if ( api.state( 'snapshot-saved' ).get() ) {
- snapshot.submitButton.prop( 'disabled', false );
- }
- } );
},
/**
- * Adds Save Button when user does not have 'customize_publish' permission.
+ * Add inspect changeset post link.
*
+ * @param {wp.customize.Section} section Section.
* @return {void}
*/
- addSaveButton: function() {
- var snapshot = this, disableSaveButton, isSaved;
-
- isSaved = _.contains( [ 'future', 'pending', 'draft' ], api.state( 'changesetStatus' ).get() );
- disableSaveButton = isSaved || ! api.state( 'snapshot-exists' ).get();
-
- snapshot.saveButton = $( $.trim( wp.template( 'snapshot-save' )( {
- buttonText: isSaved ? snapshot.data.i18n.updateButton : snapshot.data.i18n.saveButton
- } ) ) );
-
- snapshot.saveButton.prop( 'disabled', disableSaveButton );
- snapshot.saveButton.insertBefore( snapshot.publishButton );
-
- api.state( 'snapshot-submitted' ).bind( function( submitted ) {
- if ( submitted ) {
- snapshot.saveButton.prop( 'disabled', true );
- }
- } );
-
- snapshot.saveButton.on( 'click', function( event ) {
- event.preventDefault();
- snapshot.saveButton.prop( 'disabled', true );
- snapshot.submitButton.prop( 'disabled', true );
- snapshot.updateSnapshot( 'draft' ).done( function() {
- snapshot.saveButton.prop( 'disabled', true );
- snapshot.submitButton.prop( 'disabled', false );
- snapshot.saveButton.text( snapshot.data.i18n.updateButton );
- } ).fail( function() {
- snapshot.saveButton.prop( 'disabled', false );
- snapshot.submitButton.prop( 'disabled', false );
- } );
- } );
-
- snapshot.editControlSettings.bind( 'change', function() {
- if ( api.state( 'snapshot-saved' ).get() ) {
- snapshot.saveButton.prop( 'disabled', false );
- }
- } );
- },
-
- /**
- * Renders snapshot schedule and handles it's events.
- *
- * @returns {void}
- */
- editSnapshotUI: function editSnapshotUI() {
- var snapshot = this, sliceBegin = 0,
- sliceEnd = -2, updateUI, toggleDateNotification;
-
- snapshot.snapshotEditContainerDisplayed = new api.Value( false );
-
- updateUI = function() {
- snapshot.populateSetting();
- };
-
- // Inject the UI.
- if ( _.isEmpty( snapshot.editContainer ) ) {
- if ( '0000-00-00 00:00:00' === snapshot.data.publishDate ) {
- snapshot.data.publishDate = snapshot.getCurrentTime();
- }
-
- // Normalize date with secs set as zeros removed.
- snapshot.data.publishDate = snapshot.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
-
- // Extend the snapshots data object and add the parsed datetime strings.
- snapshot.data = _.extend( snapshot.data, snapshot.parseDateTime( snapshot.data.publishDate ) );
-
- // Add the template to the DOM.
- snapshot.editContainer = $( $.trim( wp.template( 'snapshot-edit-container' )( snapshot.data ) ) );
- snapshot.editContainer.hide().appendTo( $( '#customize-header-actions' ) );
- snapshot.dateNotification = snapshot.editContainer.find( '.snapshot-future-date-notification' );
- snapshot.countdown = snapshot.editContainer.find( '.snapshot-scheduled-countdown' );
- snapshot.dateControl = snapshot.editContainer.find( '.snapshot-control-date' );
-
- if ( snapshot.data.currentUserCanPublish ) {
-
- // Store the date inputs.
- snapshot.schedule.inputs = snapshot.editContainer.find( '.date-input' );
-
- snapshot.schedule.inputs.on( 'input', updateUI );
-
- snapshot.schedule.inputs.on( 'blur', function() {
- snapshot.populateInputs();
- updateUI();
+ addInspectChangesetControl: function( section ) {
+ var InspectLinkControl;
+
+ InspectLinkControl = api.Control.extend( {
+ defaults: _.extend( {}, api.Control.prototype.defaults, {
+ templateId: 'snapshot-inspect-link-control'
+ } ),
+ ready: function() {
+ var control = this, link;
+ link = control.container.find( 'a' );
+ link.attr( 'href', control.setting() );
+ control.setting.bind( function( value ) {
+ link.attr( 'href', value );
} );
- snapshot.updateCountdown();
-
- snapshot.editContainer.find( '.reset-time a' ).on( 'click', function( event ) {
- event.preventDefault();
- snapshot.updateSnapshotEditControls();
+ control.toggleInspectChangesetControl();
+ api.state( 'changesetStatus' ).bind( function() {
+ control.toggleInspectChangesetControl();
} );
- }
-
- if ( snapshot.statusButton && 'future' !== snapshot.statusButton.value.get() ) {
- snapshot.countdown.hide();
- }
-
- snapshot.snapshotTitle = snapshot.editContainer.find( '#snapshot-title' );
- snapshot.snapshotTitle.on( 'input', updateUI );
- }
-
- toggleDateNotification = function() {
- if ( ! _.isEmpty( snapshot.dateNotification ) ) {
- snapshot.dateNotification.toggle( ! snapshot.isFutureDate() );
- }
- };
-
- // Set up toggling of the schedule container.
- snapshot.snapshotEditContainerDisplayed.bind( function( isDisplayed ) {
-
- if ( snapshot.statusButton ) {
- snapshot.dateControl.toggle( 'future' === snapshot.statusButton.value.get() );
- }
-
- if ( isDisplayed ) {
- snapshot.editContainer.stop().slideDown( 'fast' ).attr( 'aria-expanded', 'true' );
- snapshot.snapshotExpandButton.attr( 'aria-pressed', 'true' );
- snapshot.snapshotExpandButton.prop( 'title', snapshot.data.i18n.collapseSnapshotScheduling );
- toggleDateNotification();
- } else {
- snapshot.editContainer.stop().slideUp( 'fast' ).attr( 'aria-expanded', 'false' );
- snapshot.snapshotExpandButton.attr( 'aria-pressed', 'false' );
- snapshot.snapshotExpandButton.prop( 'title', snapshot.data.i18n.expandSnapshotScheduling );
- }
- } );
-
- snapshot.editControlSettings( 'date' ).bind( function() {
- toggleDateNotification();
- } );
-
- // Toggle schedule container when clicking the button.
- snapshot.snapshotExpandButton.on( 'click', function() {
- snapshot.snapshotEditContainerDisplayed.set( ! snapshot.snapshotEditContainerDisplayed.get() );
- } );
-
- // Collapse the schedule container when Esc is pressed while the button is focused.
- snapshot.snapshotExpandButton.on( 'keydown', function( event ) {
- if ( escKeyCode === event.which && snapshot.snapshotEditContainerDisplayed.get() ) {
- event.stopPropagation();
- event.preventDefault();
- snapshot.snapshotEditContainerDisplayed.set( false );
- }
- } );
-
- // Collapse the schedule container when Esc is pressed inside of the schedule container.
- snapshot.editContainer.on( 'keydown', function( event ) {
- if ( escKeyCode === event.which && snapshot.snapshotEditContainerDisplayed.get() ) {
- event.stopPropagation();
- event.preventDefault();
- snapshot.snapshotEditContainerDisplayed.set( false );
- snapshot.snapshotExpandButton.focus();
- }
- } );
-
- // Collapse the schedule container interacting outside the schedule container.
- $( 'body' ).on( 'mousedown', function( event ) {
- var isDisplayed = snapshot.snapshotEditContainerDisplayed.get(),
- isTargetEditContainer = snapshot.editContainer.is( event.target ) || 0 !== snapshot.editContainer.has( event.target ).length,
- isTargetExpandButton = snapshot.snapshotExpandButton.is( event.target );
-
- if ( isDisplayed && ! isTargetEditContainer && ! isTargetExpandButton ) {
- snapshot.snapshotEditContainerDisplayed.set( false );
- }
- } );
-
- snapshot.snapshotEditContainerDisplayed.set( false );
-
- api.state( 'snapshot-saved' ).bind( function( saved ) {
- if ( saved && ! snapshot.dirtyEditControlValues ) {
- snapshot.updateSnapshotEditControls();
- }
- } );
-
- api.bind( 'change', function() {
- snapshot.data.dirty = true;
- snapshot.editContainer.find( 'a.snapshot-edit-link' ).hide();
- } );
-
- api.state( 'snapshot-exists' ).bind( function( exists ) {
- if ( exists && ! _.isEmpty( snapshot.editContainer ) ) {
- snapshot.updateSnapshotEditControls();
- } else {
- snapshot.snapshotEditContainerDisplayed.set( false );
- }
- } );
-
- if ( snapshot.statusButton ) {
- snapshot.updateSnapshotEditControls();
- }
-
- snapshot.autoSaveEditBox();
- },
-
- /**
- * Auto save the edit box values.
- *
- * @return {void}
- */
- autoSaveEditBox: function() {
- var snapshot = this, update,
- delay = 2000, status, isFutureDateAndStatus;
-
- snapshot.updatePending = false;
- snapshot.dirtyEditControlValues = false;
-
- update = _.debounce( function() {
- status = snapshot.statusButton.value.get();
- isFutureDateAndStatus = 'future' === status && ! snapshot.isFutureDate();
- if ( 'publish' === status || isFutureDateAndStatus ) {
- snapshot.updatePending = false;
- return;
- }
- snapshot.updatePending = true;
- snapshot.editBoxAutoSaveTriggered = true;
- snapshot.dirtyEditControlValues = false;
- snapshot.updateSnapshot( status ).done( function() {
- snapshot.updatePending = snapshot.dirtyEditControlValues;
- if ( ! snapshot.updatePending ) {
- snapshot.updateSnapshotEditControls();
- } else if ( snapshot.dirtyEditControlValues ) {
- update();
- }
- snapshot.dirtyEditControlValues = false;
- } ).fail( function() {
- snapshot.updatePending = false;
- snapshot.dirtyEditControlValues = true;
- } );
- }, delay );
-
- snapshot.editControlSettings( 'title' ).bind( function() {
- snapshot.dirtyEditControlValues = true;
- if ( ! snapshot.updatePending ) {
- update();
- }
- } );
-
- snapshot.editControlSettings( 'date' ).bind( function() {
- if ( snapshot.isFutureDate() ) {
- snapshot.dirtyEditControlValues = true;
- if ( ! snapshot.updatePending ) {
- update();
- }
- }
- } );
-
- $( window ).on( 'beforeunload.customize-confirm', function() {
- if ( snapshot.updatePending || snapshot.dirtyEditControlValues ) {
- return snapshot.data.i18n.aysMsg;
- }
- return undefined;
- } );
-
- // @todo Show loader and disable button while auto saving.
-
- api.bind( 'changeset-saved', function() {
- if ( 'auto-draft' !== api.state( 'changesetStatus' ).get() ) {
- api.state( 'saved' ).set( true ); // Suppress the AYS dialog.
- }
- });
- },
-
- /**
- * Get the preview URL with the snapshot UUID attached.
- *
- * @returns {string} URL.
- */
- getSnapshotFrontendPreviewUrl: function getSnapshotFrontendPreviewUrl() {
- var snapshot = this, a = document.createElement( 'a' );
- a.href = snapshot.frontendPreviewUrl.get();
- if ( a.search ) {
- a.search += '&';
- }
- a.search += snapshot.uuidParam + '=' + snapshot.data.uuid;
- return a.href;
- },
-
- /**
- * Updates snapshot schedule with `snapshot.data`.
- *
- * @return {void}
- */
- updateSnapshotEditControls: function updateSnapshotEditControls() {
- var snapshot = this,
- parsed,
- status,
- sliceBegin = 0,
- sliceEnd = -2;
-
- if ( _.isEmpty( snapshot.editContainer ) ) {
- return;
- }
-
- status = api.state( 'changesetStatus' ).get();
-
- if ( snapshot.data.currentUserCanPublish ) {
- if ( '0000-00-00 00:00:00' === snapshot.data.publishDate || ! status || 'auto-draft' === status ) {
- snapshot.data.publishDate = snapshot.getCurrentTime();
- }
-
- // Normalize date with seconds removed.
- snapshot.data.publishDate = snapshot.data.publishDate.slice( sliceBegin, sliceEnd ) + '00';
- parsed = snapshot.parseDateTime( snapshot.data.publishDate );
-
- // Update date controls.
- snapshot.schedule.inputs.each( function() {
- var input = $( this ),
- fieldName = input.data( 'date-input' );
- $( this ).val( parsed[ fieldName ] );
- } );
- }
-
- snapshot.editContainer.find( 'a.snapshot-edit-link' )
- .attr( 'href', snapshot.data.editLink )
- .show();
- if ( ! _.isEmpty( snapshot.data.title ) ) {
- snapshot.snapshotTitle.val( snapshot.data.title );
- }
- snapshot.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.
- */
- updateCountdown: function updateCountdown() {
- var snapshot = this,
- countdownTemplate = wp.template( 'snapshot-scheduled-countdown' ),
- dateTimeFromInput = snapshot.getDateFromInputs(),
- millisecondsDivider = 1000,
- remainingTime;
-
- if ( ! dateTimeFromInput ) {
- return false;
- }
-
- remainingTime = dateTimeFromInput.valueOf();
- remainingTime -= snapshot.dateValueOf( snapshot.getCurrentTime() );
- remainingTime = Math.ceil( remainingTime / millisecondsDivider );
-
- if ( 0 < remainingTime ) {
- snapshot.countdown.text( countdownTemplate( {
- remainingTime: remainingTime
- } ) );
- snapshot.countdown.show();
- } else {
- snapshot.countdown.hide();
- }
-
- return true;
- },
-
- /**
- * Get date from inputs.
- *
- * @returns {Date|null} Date created from inputs or null if invalid date.
- */
- getDateFromInputs: function getDateFromInputs() {
- var snapshot = this,
- template = snapshot.editContainer,
- 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.
- */
- 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.
- */
- formatDate: function formatDate( date ) {
- var formattedDate,
- yearLength = 4,
- nonYearLength = 2,
- monthOffset = 1;
-
- formattedDate = ( '0000' + String( date.getFullYear() ) ).substr( -yearLength, yearLength );
- formattedDate += '-' + ( '00' + String( date.getMonth() + monthOffset ) ).substr( -nonYearLength, nonYearLength );
- formattedDate += '-' + ( '00' + String( date.getDate() ) ).substr( -nonYearLength, nonYearLength );
- formattedDate += ' ' + ( '00' + String( date.getHours() ) ).substr( -nonYearLength, nonYearLength );
- formattedDate += ':' + ( '00' + String( date.getMinutes() ) ).substr( -nonYearLength, nonYearLength );
- formattedDate += ':' + ( '00' + String( 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.
- */
- populateInputs: function populateInputs() {
- var snapshot = this, parsed;
-
- if ( snapshot.schedule.inputs.is( ':focus' ) || '0000-00-00 00:00:00' === snapshot.data.publishDate ) {
- return false;
- }
-
- parsed = snapshot.parseDateTime( snapshot.data.publishDate );
- if ( ! parsed ) {
- return false;
- }
-
- snapshot.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 {void}
- */
- populateSetting: function populateSetting() {
- var snapshot = this,
- date = snapshot.getDateFromInputs(),
- scheduled;
-
- snapshot.editControlSettings( 'title' ).set( snapshot.snapshotTitle.val() );
-
- if ( ! date || ! snapshot.data.currentUserCanPublish ) {
- return;
- }
-
- date.setSeconds( 0 );
- scheduled = snapshot.formatDate( date ) !== snapshot.data.publishDate;
- snapshot.editControlSettings( 'date' ).set( snapshot.formatDate( date ) );
-
- if ( 'future' === snapshot.statusButton.value.get() ) {
- snapshot.updateCountdown();
- }
-
- snapshot.editContainer.find( '.reset-time' ).toggle( scheduled );
- },
-
- /**
- * Check if the schedule date is in the future.
- *
- * @returns {boolean} True if future date.
- */
- isFutureDate: function isFutureDate() {
- var snapshot = this,
- date = snapshot.getDateFromInputs(),
- millisecondsDivider = 1000,
- remainingTime;
-
- if ( ! date ) {
- return false;
- }
-
- remainingTime = snapshot.dateValueOf( date );
- remainingTime -= snapshot.dateValueOf( snapshot.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.
- */
- getCurrentTime: function getCurrentTime() {
- var snapshot = this, currentDate, currentTimestamp, timestampDifferential;
- currentTimestamp = ( new Date() ).valueOf();
- currentDate = snapshot.parsePostDate( snapshot.data.initialServerDate );
- timestampDifferential = currentTimestamp - snapshot.data.initialClientTimestamp;
- timestampDifferential += snapshot.data.initialClientTimestamp - snapshot.data.initialServerTimestamp;
- currentDate.setTime( currentDate.getTime() + timestampDifferential );
- return snapshot.formatDate( currentDate );
- },
-
- /**
- * Parse post date string in YYYY-MM-DD HH:MM:SS format (local timezone).
- *
- * @param {string} postDate Post date string.
- * @returns {Date} Parsed date.
- */
- parsePostDate: function parsePostDate( postDate ) {
- var dateParts = _.map( postDate.split( /\D/ ), function( datePart ) {
- return parseInt( datePart, 10 );
- } );
- return new Date( dateParts[0], dateParts[1] - 1, dateParts[2], dateParts[3], dateParts[4], dateParts[5] ); // eslint-disable-line no-magic-numbers
- },
-
- /**
- * 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.
- */
- dateValueOf: function dateValueOf( 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();
- },
-
- /**
- * Amend the preview query so we can update the snapshot during `changeset_save`.
- *
- * @return {void}
- */
- extendPreviewerQuery: function extendPreviewerQuery() {
- var snapshot = this, originalQuery = api.previewer.query;
-
- api.previewer.query = function() {
- var retval = originalQuery.apply( this, arguments );
-
- if ( ! _.contains( [ 'future', 'pending', 'draft' ], snapshot.statusButton.value.get() ) ) {
- return retval;
- }
-
- retval.customizer_state_query_vars = JSON.stringify( snapshot.getStateQueryVars() );
-
- if ( snapshot.editControlSettings( 'title' ).get() ) {
- retval.customize_changeset_title = snapshot.editControlSettings( 'title' ).get();
- }
- if ( snapshot.editControlSettings( 'date' ).get() && snapshot.isFutureDate() ) {
- retval.customize_changeset_date = snapshot.editControlSettings( 'date' ).get();
- }
- return retval;
- };
- },
-
- /**
- * Add status button.
- *
- * @return {object} status button.
- */
- addStatusButton: function addStatusButton() {
- var snapshot = this, selectMenuButton, statusButton, selectedOption, buttonText, changesetStatus, selectedStatus;
- changesetStatus = api.state( 'changesetStatus' ).get();
- statusButton = {};
-
- selectedStatus = changesetStatus && 'auto-draft' !== changesetStatus ? changesetStatus : 'publish';
-
- statusButton.value = new api.Value( selectedStatus );
- statusButton.disbleButton = new api.Value();
- statusButton.disableSelect = new api.Value();
- statusButton.buttonText = new api.Value();
- statusButton.needConfirm = false;
-
- statusButton.container = $( $.trim( wp.template( 'snapshot-status-button' )({
- selected: selectedStatus
- }) ) );
- statusButton.button = statusButton.container.find( '.snapshot-status-button-overlay' );
- statusButton.select = statusButton.container.find( 'select' );
- statusButton.select.selectmenu({
- width: 'auto',
- icons: {
- button: 'dashicons dashicons-arrow-down'
- },
- change: function( event, ui ) {
- statusButton.value.set( ui.item.value );
},
- select: function() {
- if ( statusButton.hiddenButton ) {
- statusButton.hiddenButton.text( statusButton.buttonText.get() );
- }
+ toggleInspectChangesetControl: function() {
+ this.active.set( ! _.contains( [ '', 'auto-draft' ], api.state( 'changesetStatus' ).get() ) );
}
- });
-
- selectMenuButton = statusButton.container.find( '.ui-selectmenu-button' );
- statusButton.hiddenButton = selectMenuButton.find( '.ui-selectmenu-text' );
- statusButton.hiddenButton.addClass( 'button button-primary' );
-
- statusButton.dropDown = selectMenuButton.find( '.ui-icon' );
- statusButton.dropDown.addClass( 'button button-primary' );
-
- statusButton.updateButtonText = function( dataAttr ) {
- buttonText = statusButton.button.data( dataAttr );
- statusButton.button.text( buttonText );
- statusButton.hiddenButton.text( buttonText );
- statusButton.buttonText.set( buttonText );
- };
-
- statusButton.value.bind( function( status ) {
- selectedOption = statusButton.select.find( 'option:selected' );
- statusButton.button.data( 'alt-text', selectedOption.data( 'alt-text' ) );
- statusButton.button.data( 'button-text', selectedOption.text() );
- statusButton.updateButtonText( 'button-text' );
-
- if ( 'publish' === status ) {
- snapshot.snapshotExpandButton.hide();
- statusButton.button.data( 'confirm-text', selectedOption.data( 'confirm-text' ) );
- statusButton.button.data( 'publish-text', selectedOption.data( 'publish-text' ) );
- statusButton.needConfirm = true;
- }
-
- if ( 'future' === status ) {
- snapshot.snapshotEditContainerDisplayed.set( true );
- snapshot.snapshotExpandButton.show();
- if ( snapshot.isFutureDate() ) {
- snapshot.countdown.show();
- snapshot.updateSnapshot( status );
- }
- } else {
- snapshot.updateSnapshot( status );
- snapshot.snapshotEditContainerDisplayed.set( false );
- snapshot.countdown.hide();
- }
- } );
-
- statusButton.disbleButton.bind( function( disabled ) {
- statusButton.button.prop( 'disabled', disabled );
} );
- statusButton.disableSelect.bind( function( disabled ) {
- statusButton.select.selectmenu( disabled ? 'disable' : 'enable' );
- statusButton.dropDown.toggleClass( 'disabled', disabled );
- } );
-
- statusButton.disable = function( disable ) {
- statusButton.disableSelect.set( disable );
- statusButton.disbleButton.set( disable );
- };
-
- statusButton.button.on( 'click', function( event ) {
- event.preventDefault();
- snapshot.updateSnapshot( statusButton.value.get() );
- } );
-
- snapshot.publishButton.after( statusButton.container );
-
- return statusButton;
+ api.control.add( new InspectLinkControl( 'inspect_changeset', {
+ type: 'inspect-changeset-link',
+ section: section.id,
+ priority: 30,
+ setting: api.state( 'changesetInspectUrl' )
+ } ) );
},
/**
- * Remove 'customize_changeset_status' if it is being auto saved for edit box to avoid revisions.
+ * Add pending status to changeset status control.
*
* @return {void}
*/
- prefilterAjax: function prefilterAjax() {
- var snapshot = this, removeParam, isSameStatus;
+ addPendingToStatusControl: function() {
+ var snapshot = this, params, coreStatusControl, draftIndex = 0;
- if ( ! api.state.has( 'changesetStatus' ) ) {
- return;
- }
+ coreStatusControl = api.control( 'changeset_status' );
- removeParam = function( queryString, parameter ) {
- var pars = queryString.split( /[&;]/g );
+ coreStatusControl.deferred.embedded.done( function() {
+ params = _.extend( {}, coreStatusControl.params );
+ coreStatusControl.container.remove();
+ api.control.remove( 'changeset_status' );
- _.each( pars, function( string, index ) {
- if ( string && string.lastIndexOf( parameter, 0 ) !== -1 ) {
- pars.splice( index, 1 );
+ _.each( params.choices, function( statusConfig, index ) {
+ if ( 'draft' === statusConfig.status ) {
+ draftIndex = index;
}
} );
- return pars.join( '&' );
- };
-
- $.ajaxPrefilter( function( options, originalOptions ) {
- if ( ! originalOptions.data || ! snapshot.editBoxAutoSaveTriggered ) {
- return;
- }
-
- isSameStatus = api.state( 'changesetStatus' ).get() === originalOptions.data.customize_changeset_status;
- if ( 'customize_save' === originalOptions.data.action && options.data && originalOptions.data.customize_changeset_status && isSameStatus ) {
- options.data = removeParam( options.data, 'customize_changeset_status' );
- snapshot.editBoxAutoSaveTriggered = false;
- }
+ params.choices.splice( draftIndex + 1, 0, {
+ label: snapshot.data.i18n.savePending,
+ status: 'pending'
+ } );
+ api.control.add( new api.Control( 'changeset_status', params ) );
} );
},
/**
- * Remove a param from close button link.
- *
- * @param {string} targetParam param.
- * @return {void}.
- */
- removeParamFromClose: function removeParamFromClose( targetParam ) {
- var snapshot = this, closeButton, queryString, updatedParams;
- closeButton = $( '.customize-controls-close' );
- queryString = closeButton.prop( 'search' ).substr( 1 );
-
- if ( ! queryString.length ) {
- return;
- }
-
- updatedParams = snapshot.parseQueryString( queryString );
- delete updatedParams[ targetParam ];
- closeButton.prop( 'search', $.param( updatedParams ) );
- },
-
- /**
- * Parse query string.
+ * Get the preview URL with the snapshot UUID attached for backward compat.
*
- * @since 4.7.0
- * @access public
- *
- * @param {string} queryString Query string.
- * @returns {object} Parsed query string.
+ * @returns {string} URL.
*/
- parseQueryString: api.utils.parseQueryString
+ getSnapshotFrontendPreviewUrl: function() {
+ return api.previewer.getFrontendPreviewUrl();
+ }
} );
- if ( 'undefined' !== typeof _customizeSnapshotsSettings ) {
- api.snapshots = new api.Snapshots( _customizeSnapshotsSettings );
- }
-
})( wp.customize, jQuery );
diff --git a/package.json b/package.json
index d2765bc7..b4d8753d 100644
--- a/package.json
+++ b/package.json
@@ -9,14 +9,14 @@
"author": "XWP",
"license": "GPL-2.0+",
"devDependencies": {
- "eslint": "^3.2.2",
- "grunt": "~0.4.5",
- "grunt-contrib-clean": "~1.0.0",
+ "eslint": "^4.5.0",
+ "grunt": "~1.0.1",
+ "grunt-contrib-clean": "~1.1.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"
+ "grunt-contrib-cssmin": "~2.2.1",
+ "grunt-contrib-jshint": "~1.1.0",
+ "grunt-contrib-uglify": "~3.0.1",
+ "grunt-shell": "~2.1.0",
+ "grunt-wp-deploy": "~1.2.1"
}
}
diff --git a/php/class-customize-snapshot-back-compat.php b/php/class-customize-snapshot-back-compat.php
deleted file mode 100644
index 2afa58d4..00000000
--- a/php/class-customize-snapshot-back-compat.php
+++ /dev/null
@@ -1,325 +0,0 @@
-snapshot_manager = $snapshot_manager;
- $this->data = array();
-
- if ( ! Customize_Snapshot_Manager_Back_Compat::is_valid_uuid( $uuid ) ) {
- throw new Exception( __( 'You\'ve entered an invalid snapshot UUID.', 'customize-snapshots' ) );
- }
- $this->uuid = $uuid;
- $post = $this->post();
- if ( $post ) {
- $this->data = $this->snapshot_manager->post_type->get_post_content( $post );
- }
- parent::__construct( $snapshot_manager );
- }
-
- /**
- * Get the snapshot uuid.
- *
- * @return string
- */
- public function uuid() {
- return $this->uuid;
- }
-
- /**
- * Get the underlying data for the snapshot.
- *
- * @return array
- */
- public function data() {
- return $this->data;
- }
-
- /**
- * Get the status of the snapshot.
- *
- * @return string|null
- */
- public function status() {
- $post = $this->post();
- return $post ? get_post_status( $post->ID ) : null;
- }
-
- /**
- * Get the snapshot post associated with the provided UUID, or null if it does not exist.
- *
- * @return \WP_Post|null Post or null.
- */
- public function post() {
- if ( ! $this->post_id ) {
- $this->post_id = $this->snapshot_manager->post_type->find_post( $this->uuid );
- }
- if ( $this->post_id ) {
- return get_post( $this->post_id );
- } else {
- return null;
- }
- }
-
- /**
- * Return the Customizer settings corresponding to the data contained in the snapshot.
- *
- * @return \WP_Customize_Setting[]
- */
- public function settings() {
- $settings = array();
- $setting_ids = array_keys( $this->data );
- $this->snapshot_manager->customize_manager->add_dynamic_settings( $setting_ids );
- foreach ( $setting_ids as $setting_id ) {
- $setting = $this->snapshot_manager->customize_manager->get_setting( $setting_id );
- if ( $setting ) {
- $settings[] = $setting;
- }
- }
- return $settings;
- }
-
- /**
- * Prepare snapshot data for saving.
- *
- * @see WP_Customize_Manager::set_post_value()
- * @throws Exception When $settings_data is not an array of arrays.
- *
- * @param array $settings_data Settings data, mapping setting IDs to arrays containing `value` and optionally additional params.
- * @param array $options {
- * Additional options.
- *
- * @type bool $skip_validation Whether to skip validation. Optional, defaults to false.
- * }
- * @return array {
- * Result.
- *
- * @type null|\WP_Error $error Error object if error.
- * @type array $sanitized Sanitized values.
- * @type array $validities Setting validities.
- * }
- */
- public function set( array $settings_data, array $options = array() ) {
- $error = new \WP_Error();
- $result = array(
- 'errors' => null,
- 'sanitized' => array(),
- 'validities' => array(),
- );
-
- $setting_ids = array_keys( $settings_data );
- $customize_manager = $this->snapshot_manager->customize_manager;
- $customize_manager->add_dynamic_settings( $setting_ids );
-
- // Check for recognized settings and authorized settings.
- $unsanitized_values = array();
- $unrecognized_setting_ids = array();
- $unauthorized_setting_ids = array();
- foreach ( $settings_data as $setting_id => $setting_params ) {
- if ( ! is_array( $setting_params ) ) {
- throw new Exception( '$setting_params not an array' );
- }
- $setting = $customize_manager->get_setting( $setting_id );
- if ( ! $setting ) {
- $unrecognized_setting_ids[] = $setting_id;
- } elseif ( ! current_user_can( $setting->capability ) ) {
- $unauthorized_setting_ids[] = $setting_id;
- } elseif ( array_key_exists( 'value', $setting_params ) ) {
- $unsanitized_values[ $setting_id ] = $setting_params['value'];
- }
- }
-
- // Remove values that are unrecognized or unauthorized.
- $unsanitized_values = wp_array_slice_assoc(
- $unsanitized_values,
- array_diff(
- array_keys( $unsanitized_values ),
- array_merge( $unrecognized_setting_ids, $unauthorized_setting_ids )
- )
- );
-
- $invalid_setting_ids = array();
- if ( empty( $options['skip_validation'] ) ) {
- // Validate.
- if ( method_exists( $customize_manager, 'validate_setting_values' ) ) {
- $result['validities'] = $customize_manager->validate_setting_values( $unsanitized_values );
- } else {
- // @codeCoverageIgnoreStart
- $result['validities'] = array_map(
- function( $sanitized ) {
- if ( is_null( $sanitized ) ) {
- return new \WP_Error( 'invalid_value', __( 'Invalid value', 'customize-snapshots' ) );
- } else {
- return true;
- }
- },
- $unsanitized_values
- );
- // @codeCoverageIgnoreEnd
- }
- $invalid_setting_ids = array_keys( array_filter( $result['validities'], function( $validity ) {
- return is_wp_error( $validity );
- } ) );
- }
-
- // Sanitize.
- foreach ( $unsanitized_values as $setting_id => $unsanitized_value ) {
- $setting = $customize_manager->get_setting( $setting_id );
- if ( $setting ) {
- $result['sanitized'][ $setting_id ] = $setting->sanitize( $unsanitized_value );
- } else {
- $unrecognized_setting_ids[] = $setting_id;
- }
- }
-
- // Add errors.
- if ( ! empty( $unauthorized_setting_ids ) ) {
- $error->add(
- 'unauthorized_settings',
- /* translators: %s is the list of unauthorized setting ids */
- sprintf( __( 'Unauthorized settings: %s', 'customize-snapshots' ), join( ',', $unauthorized_setting_ids ) ),
- array(
- 'setting_ids' => $unauthorized_setting_ids,
- )
- );
- }
- if ( ! empty( $unrecognized_setting_ids ) ) {
- $error->add(
- 'unrecognized_settings',
- /* translators: %s is the list of unrecognized setting ids */
- sprintf( __( 'Unrecognized settings: %s', 'customize-snapshots' ), join( ',', $unrecognized_setting_ids ) ),
- array(
- 'setting_ids' => $unrecognized_setting_ids,
- )
- );
- }
- if ( 0 !== count( $invalid_setting_ids ) ) {
- $code = 'invalid_values';
- $message = __( 'Invalid values', 'customize-snapshots' );
- $error->add( $code, $message, compact( 'invalid_setting_ids' ) );
- }
-
- if ( ! empty( $error->errors ) ) {
- $result['errors'] = $error;
- } else {
- /*
- * Note that somewhat unintuitively the unsanitized post values
- * ($unsanitized_values) are stored as opposed to storing the
- * sanitized ones ($result['sanitized']). It is still safe to do this
- * because they have passed sanitization and validation here. The
- * reason why we need to store the raw unsanitized values is so that
- * the values can be re-populated into the post values for running
- * through the sanitize, validate, and ultimately update logic.
- * Once a value has gone through the sanitize logic, it may not be
- * suitable for populating into a post value, especially widget
- * instances which get exported with a JS value that has the instance
- * data encoded, serialized, and hashed to prevent mutation. A
- * sanitize filter for a widget instance will convert an encoded
- * instance value into a regular instance array, and if this regular
- * instance array is placed back into a post value, it will get
- * rejected by the sanitize logic for not being an encoded value.
- */
- foreach ( $settings_data as $setting_id => $setting_params ) {
- if ( ! isset( $this->data[ $setting_id ] ) ) {
- $this->data[ $setting_id ] = array();
- }
- if ( ! array_key_exists( 'value', $setting_params ) ) {
- $setting_params['value'] = null;
- }
- $this->data[ $setting_id ] = array_merge( $this->data[ $setting_id ], $setting_params );
- }
- }
-
- return $result;
- }
-
- /**
- * Persist the data in the snapshot post content.
- *
- * @param array $args Args.
- * @return true|\WP_Error
- */
- public function save( array $args ) {
-
- /**
- * Filter the snapshot's data before it's saved to 'post_content'.
- *
- * @param array $data Customizer snapshot data, with setting IDs mapped to an array
- * containing a `value` array item and potentially other metadata.
- * @param Customize_Snapshot $this Snapshot object.
- */
- $this->data = apply_filters( 'customize_snapshot_save', $this->data, $this );
-
- $result = $this->snapshot_manager->post_type->save( array_merge(
- $args,
- array(
- 'uuid' => $this->uuid,
- 'data' => $this->data,
- 'theme' => $this->snapshot_manager->customize_manager->get_stylesheet(),
- )
- ) );
-
- if ( ! is_wp_error( $result ) ) {
- $this->post_id = $result;
- }
-
- return $result;
- }
-
- /**
- * Return whether the snapshot was saved (created/inserted) yet.
- *
- * @return bool
- */
- public function saved() {
- return ! is_null( $this->post() );
- }
-}
diff --git a/php/class-customize-snapshot-command.php b/php/class-customize-snapshot-command.php
deleted file mode 100644
index e2103afe..00000000
--- a/php/class-customize-snapshot-command.php
+++ /dev/null
@@ -1,61 +0,0 @@
-plugin->compat ) {
- \WP_CLI::error( __( 'You\'re using older WordPress version please upgrade 4.7 or above to migrate.', 'customize-snapshots' ) );
- return;
- }
- if ( $migrate_obj->is_migrated() ) {
- \WP_CLI::success( __( 'Already migrated.', 'customize-snapshots' ) );
- return;
- }
- $dry_mode = isset( $assoc_args['dry-run'] );
- if ( ! $dry_mode ) {
- wp_suspend_cache_addition( true );
- $post_count = $migrate_obj->changeset_migrate();
- } else {
- $ids = $migrate_obj->changeset_migrate( -1, true );
- \WP_CLI::success( __( 'Posts migrated:', 'customize-snapshots' ) . ' ' . implode( ',', $ids ) );
- $post_count = count( $ids );
- }
- /* translators: %s: post count.*/
- \WP_CLI::success( sprintf( __( 'Total posts migrated: %s', 'customize-snapshots' ), $post_count ) );
- }
-}
-
-if ( defined( 'WP_CLI' ) && WP_CLI ) {
- \WP_CLI::add_command( 'customize-snapshots', __NAMESPACE__ . '\\Customize_Snapshot_Command' );
-}
diff --git a/php/class-customize-snapshot-manager-back-compat.php b/php/class-customize-snapshot-manager-back-compat.php
deleted file mode 100644
index 78c23c6c..00000000
--- a/php/class-customize-snapshot-manager-back-compat.php
+++ /dev/null
@@ -1,1030 +0,0 @@
-post_type = new Post_Type_Back_Compat( $this );
-
- add_filter( 'customize_refresh_nonces', array( $this, 'filter_customize_refresh_nonces' ) );
- add_action( 'template_redirect', array( $this, 'show_theme_switch_error' ) );
- add_action( 'customize_save_after', array( $this, 'publish_snapshot_with_customize_save_after' ) );
- add_action( 'transition_post_status', array( $this, 'save_settings_with_publish_snapshot' ), 10, 3 );
- add_action( 'wp_ajax_' . self::AJAX_ACTION, array( $this, 'handle_update_snapshot_request' ) );
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
- add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
- add_action( 'customize_save', array( $this, 'check_customize_publish_authorization' ), 10, 0 );
- $this->hooks();
- if ( $this->read_current_snapshot_uuid() ) {
- $this->load_snapshot();
- } elseif ( is_customize_preview() && isset( $_REQUEST['wp_customize_preview_ajax'] ) && 'true' === $_REQUEST['wp_customize_preview_ajax'] ) { // WPCS: input var ok; CSRF ok.
- add_action( 'wp_loaded', array( $this, 'setup_preview_ajax_requests' ), 12 );
- }
- }
-
- /**
- * Get the Customize_Snapshot instance.
- *
- * @return Customize_Snapshot_Back_Compat
- */
- public function snapshot() {
- return $this->snapshot;
- }
-
- /**
- * Ensure Customizer manager is instantiated.
- *
- * @global \WP_Customize_Manager $wp_customize
- */
- public function ensure_customize_manager() {
- global $wp_customize;
- if ( empty( $wp_customize ) || ! ( $wp_customize instanceof \WP_Customize_Manager ) ) {
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $wp_customize = new \WP_Customize_Manager(); // WPCS: override ok.
- }
- $this->customize_manager = $wp_customize;
- }
-
- /**
- * Include the snapshot nonce in the Customizer nonces.
- *
- * @param array $nonces Nonces.
- * @return array Nonces.
- */
- public function filter_customize_refresh_nonces( $nonces ) {
- $nonces['snapshot'] = wp_create_nonce( self::AJAX_ACTION );
- return $nonces;
- }
-
- /**
- * Enqueue styles & scripts for the Customizer.
- *
- * @action customize_controls_enqueue_scripts
- * @global \WP_Customize_Manager $wp_customize
- */
- public function enqueue_controls_scripts() {
- $this->ensure_customize_manager();
-
- wp_enqueue_style( 'customize-snapshots' );
- wp_enqueue_script( 'customize-snapshots-compat' );
-
- if ( $this->snapshot ) {
- $post = $this->snapshot->post();
- $this->override_post_date_default_data( $post );
- $preview_url_query_vars = $this->post_type->get_customizer_state_query_vars( $post->ID );
- }
-
- // 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' => isset( $post ) ? get_edit_post_link( $post, 'raw' ) : '',
- 'publishDate' => isset( $post->post_date ) ? $post->post_date : '',
- 'title' => isset( $post->post_title ) ? $post->post_title : '',
- 'postStatus' => isset( $post->post_status ) ? $post->post_status : '',
- 'currentUserCanPublish' => current_user_can( 'customize_publish' ),
- 'initialServerDate' => current_time( 'mysql', false ),
- 'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
- 'theme' => $this->original_stylesheet,
- 'previewingTheme' => isset( $preview_url_query_vars['theme'] ) ? $preview_url_query_vars['theme'] : '',
- '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' ),
- 'published' => __( 'Published', 'customize-snapshots' ),
- 'permsMsg' => array(
- 'save' => __( 'You do not have permission to publish changes, but you can create a snapshot by clicking the "Save" button.', 'customize-snapshots' ),
- 'update' => __( 'You do not have permission to publish changes, but you can modify this snapshot by clicking the "Update" button.', 'customize-snapshots' ),
- ),
- 'errorMsg' => __( 'The snapshot could not be saved.', 'customize-snapshots' ),
- 'errorTitle' => __( 'Error', 'customize-snapshots' ),
- 'collapseSnapshotScheduling' => __( 'Collapse snapshot scheduling', 'customize-snapshots' ),
- 'expandSnapshotScheduling' => __( 'Expand snapshot scheduling', 'customize-snapshots' ),
- ),
- 'snapshotExists' => ( $this->snapshot && $this->snapshot->saved() ),
- ) );
-
- wp_scripts()->add_inline_script(
- 'customize-snapshots-compat',
- sprintf( 'var _customizeSnapshotsCompatSettings = %s;', wp_json_encode( $exports ) ),
- 'before'
- );
- }
-
- /**
- * Load snapshot.
- */
- public function load_snapshot() {
- $this->ensure_customize_manager();
- $this->snapshot = new Customize_Snapshot_Back_Compat( $this, $this->current_snapshot_uuid );
-
- if ( ! $this->should_import_and_preview_snapshot( $this->snapshot ) ) {
- return;
- }
-
- $this->add_widget_setting_preview_filters();
- $this->add_nav_menu_setting_preview_filters();
-
- /*
- * Populate post values.
- *
- * Note we have to defer until setup_theme since the transaction
- * can be set beforehand, and wp_magic_quotes() would not have
- * been called yet, resulting in a $_POST['customized'] that is
- * double-escaped. Note that this happens at priority 1, which
- * is immediately after Customize_Snapshot_Manager::store_customized_post_data
- * which happens at setup_theme priority 0, so that the initial
- * POST data can be preserved.
- */
- if ( did_action( 'setup_theme' ) ) {
- $this->import_snapshot_data();
- } else {
- add_action( 'setup_theme', array( $this, 'import_snapshot_data' ) );
- }
-
- // Block the robots.
- add_action( 'wp_head', 'wp_no_robots' );
-
- // Preview post values.
- if ( did_action( 'wp_loaded' ) ) {
- $this->preview_snapshot_settings();
- } else {
- add_action( 'wp_loaded', array( $this, 'preview_snapshot_settings' ), 11 );
- }
- }
-
- /**
- * Populate post values and $_POST['customized'] wth the snapshot's data.
- *
- * Plugins used to have to dynamically register settings by inspecting the
- * $_POST['customized'] var and manually re-parse and inspect to see if it
- * contains settings that wouldn't be registered otherwise. This ensures
- * that these plugins will continue to work.
- *
- * Note that this can't be called prior to the setup_theme action or else
- * magic quotes may end up getting added twice.
- *
- * @see Customize_Snapshot_Manager::should_import_and_preview_snapshot()
- */
- public function import_snapshot_data() {
- /*
- * We don't merge the snapshot data with any existing existing unsanitized
- * post values since should_import_and_preview_snapshot returns false if
- * there is any existing data in the Customizer state. This is to prevent
- * clobbering existing values (or previewing non-snapshotted values on frontend).
- * Note that wp.customize.Snapshots.extendPreviewerQuery() will extend the
- * previewer data to include the current snapshot UUID.
- */
- $snapshot_values = array_filter(
- wp_list_pluck( $this->snapshot->data(), 'value' ),
- function( $value ) {
- return ! is_null( $value );
- }
- );
-
- // Populate input vars for back-compat.
- $_POST['customized'] = wp_slash( wp_json_encode( $snapshot_values ) );
- // @codingStandardsIgnoreStart
- $_REQUEST['customized'] = $_POST['customized'];
- // @codingStandardsIgnoreEnd
-
- foreach ( $snapshot_values as $setting_id => $value ) {
- $this->customize_manager->set_post_value( $setting_id, $value );
- }
- }
-
- /**
- * Determine whether the current snapshot can be previewed.
- *
- * @param Customize_Snapshot_Back_Compat $snapshot Snapshot to check.
- * @return true|\WP_Error Returns true if previewable, or `WP_Error` if cannot.
- */
- public function should_import_and_preview_snapshot( Customize_Snapshot_Back_Compat $snapshot ) {
- global $pagenow;
-
- // Ignore if in the admin, but not Admin Ajax or Customizer.
- if ( is_admin() && ! in_array( $pagenow, array( 'admin-ajax.php', 'customize.php' ), true ) ) {
- return false;
- }
-
- if ( is_wp_error( $this->get_theme_switch_error( $snapshot ) ) ) {
- return false;
- }
-
- // Abort if doing customize_save.
- if ( $this->doing_customize_save_ajax() ) {
- return false;
- }
-
- // Abort if the snapshot was already published.
- if ( $snapshot->saved() && 'publish' === get_post_status( $snapshot->post() ) ) {
- return false;
- }
-
- /*
- * Prevent clobbering existing values (or previewing non-snapshotted values on frontend).
- * Note that wp.customize.Snapshots.extendPreviewerQuery() will extend the
- * previewer data to include the current snapshot UUID.
- */
- if ( $this->customize_manager && count( $this->customize_manager->unsanitized_post_values() ) > 0 ) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Redirect when preview is not allowed for the current theme.
- *
- * @param Customize_Snapshot $snapshot Snapshot to check.
- * @return \WP_Error|null
- */
- public function get_theme_switch_error( Customize_Snapshot $snapshot ) {
-
- // Loading a snapshot into the context of a theme switch is not supported.
- if ( ! $this->is_theme_active() ) {
- return new \WP_Error( 'snapshot_theme_switch', __( 'Snapshot cannot be previewed when previewing a theme switch.', 'customize-snapshots' ) );
- }
-
- $snapshot_post = $snapshot->post();
- if ( ! $snapshot_post ) {
- return null;
- }
-
- $snapshot_theme = get_post_meta( $snapshot_post->ID, '_snapshot_theme', true );
- if ( ! empty( $snapshot_theme ) && get_stylesheet() !== $snapshot_theme ) {
- return new \WP_Error( 'snapshot_theme_switched', __( 'Snapshot requested was made for a different theme and cannot be previewed with the current theme.', 'customize-snapshots' ) );
- }
-
- return null;
- }
-
- /**
- * Is previewing settings.
- *
- * Plugins and themes may currently only use `is_customize_preview()` to
- * decide whether or not they can store a value in the object cache. For
- * example, see `Twenty_Eleven_Ephemera_Widget::widget()`. However, when
- * viewing a snapshot on the frontend, the `is_customize_preview()` method
- * will return `false`. Plugins and themes that store values in the object
- * cache must either skip doing this when `$this->previewing` is `true`,
- * or include the `$this->current_snapshot_uuid` (`current_snapshot_uuid()`)
- * in the cache key when it is `true`. Note that if the `customize_preview_init` action
- * was done, this means that the settings have been previewed in the regular
- * Customizer preview.
- *
- * @see Twenty_Eleven_Ephemera_Widget::widget()
- * @see WP_Customize_Manager::is_previewing_settings()
- * @see is_previewing_settings()
- * @see current_snapshot_uuid()()
- * @see WP_Customize_Manager::customize_preview_init()
- * @see Customize_Snapshot_Manager::$previewing_settings
- *
- * @return bool Whether previewing settings.
- */
- public function is_previewing_settings() {
- return $this->previewing_settings || did_action( 'customize_preview_init' );
- }
-
- /**
- * Preview the snapshot settings.
- *
- * Note that this happens at `wp_loaded` action with priority 11 so that we
- * can look at whether the `customize_preview_init` action was done.
- */
- public function preview_snapshot_settings() {
- if ( $this->is_previewing_settings() ) {
- return;
- }
- $this->previewing_settings = true;
-
- /*
- * Note that we need to preview the settings outside the Customizer preview
- * and in the Customizer pane itself so we can load a previous snapshot
- * into the Customizer. We have to prevent the previews from being added
- * in the case of a customize_save action because then update_option()
- * may short-circuit because it will detect that there are no changes to
- * make.
- */
- foreach ( $this->snapshot->settings() as $setting ) {
- $setting->preview();
- $setting->dirty = true;
- }
- }
-
- /**
- * Add filters for previewing widgets on the frontend.
- */
- function add_widget_setting_preview_filters() {
- /*
- * Add WP_Customize_Widget component hooks which were short-circuited in 4.5 (r36611 for #35895).
- * See https://core.trac.wordpress.org/ticket/35895
- */
- if ( isset( $this->customize_manager->widgets ) && ! current_user_can( 'edit_theme_options' ) ) {
- $hooks = array(
- 'customize_dynamic_setting_args' => array(
- 'callback' => array( $this->customize_manager->widgets, 'filter_customize_dynamic_setting_args' ),
- 'priority' => 10,
- ),
- 'widgets_init' => array(
- 'callback' => array( $this->customize_manager->widgets, 'register_settings' ),
- 'priority' => 95,
- ),
- 'customize_register' => array(
- 'callback' => array( $this->customize_manager->widgets, 'schedule_customize_register' ),
- 'priority' => 1,
- ),
- );
- foreach ( $hooks as $hook_name => $hook_args ) {
- // Note that add_action()/has_action() are just aliases for add_filter()/has_filter().
- if ( ! has_filter( $hook_name, $hook_args['callback'] ) ) {
- add_filter( $hook_name, $hook_args['callback'], $hook_args['priority'], PHP_INT_MAX );
- }
- }
- }
-
- /*
- * Disable routine which fails because \WP_Customize_Manager::setup_theme() is
- * never called in a frontend preview context, whereby the original_stylesheet
- * is never set and so \WP_Customize_Manager::is_theme_active() will thus
- * always return true because get_stylesheet() !== null.
- *
- * The action being removed is responsible for adding an option_sidebar_widgets
- * filter \WP_Customize_Widgets::filter_option_sidebars_widgets_for_theme_switch()
- * which causes the sidebars_widgets to be overridden with a global variable.
- */
- if ( ! is_admin() ) {
- remove_action( 'wp_loaded', array( $this->customize_manager->widgets, 'override_sidebars_widgets_for_theme_switch' ) );
- }
- }
-
- /**
- * Add filters for previewing nav menus on the frontend.
- */
- public function add_nav_menu_setting_preview_filters() {
- if ( isset( $this->customize_manager->nav_menus ) && ! current_user_can( 'edit_theme_options' ) ) {
- $hooks = array(
- 'customize_register' => array(
- 'callback' => array( $this->customize_manager->nav_menus, 'customize_register' ),
- 'priority' => 11,
- ),
- 'customize_dynamic_setting_args' => array(
- 'callback' => array( $this->customize_manager->nav_menus, 'filter_dynamic_setting_args' ),
- 'priority' => 10,
- ),
- 'customize_dynamic_setting_class' => array(
- 'callback' => array( $this->customize_manager->nav_menus, 'filter_dynamic_setting_class' ),
- 'priority' => 10,
- ),
- 'wp_nav_menu_args' => array(
- 'callback' => array( $this->customize_manager->nav_menus, 'filter_wp_nav_menu_args' ),
- 'priority' => 1000,
- ),
- 'wp_nav_menu' => array(
- 'callback' => array( $this->customize_manager->nav_menus, 'filter_wp_nav_menu' ),
- 'priority' => 10,
- ),
- );
- foreach ( $hooks as $hook_name => $hook_args ) {
- // Note that add_action()/has_action() are just aliases for add_filter()/has_filter().
- if ( ! has_filter( $hook_name, $hook_args['callback'] ) ) {
- add_filter( $hook_name, $hook_args['callback'], $hook_args['priority'], PHP_INT_MAX );
- }
- }
- }
-
- if ( isset( $this->customize_manager->nav_menus ) ) {
- add_action( 'customize_register', array( $this, 'preview_early_nav_menus_in_customizer' ), 9 );
- }
- }
-
- /**
- * Preview nav menu settings early so that the sections and controls for snapshot values will be added properly.
- *
- * This must happen at `customize_register` priority prior to 11 which is when `WP_Customize_Nav_Menus::customize_register()` runs.
- * This is only relevant when accessing the Customizer app (customize.php), as this is where sections/controls matter.
- *
- * @see \WP_Customize_Nav_Menus::customize_register()
- */
- public function preview_early_nav_menus_in_customizer() {
- if ( ! is_admin() ) {
- return;
- }
- $this->customize_manager->add_dynamic_settings( array_keys( $this->snapshot()->data() ) );
- foreach ( $this->snapshot->settings() as $setting ) {
- $is_nav_menu_setting = (
- $setting instanceof \WP_Customize_Nav_Menu_Setting
- ||
- $setting instanceof \WP_Customize_Nav_Menu_Item_Setting
- ||
- preg_match( '/^nav_menu_locations\[/', $setting->id )
- );
- 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;
- }
- }
- }
-
- /**
- * Setup previewing of Ajax requests in the Customizer preview.
- *
- * @global \WP_Customize_Manager $wp_customize
- */
- public function setup_preview_ajax_requests() {
- global $wp_customize, $pagenow;
-
- /*
- * When making admin-ajax requests from the frontend, settings won't be
- * previewed because is_admin() and the call to preview will be
- * short-circuited in \WP_Customize_Manager::wp_loaded().
- */
- if ( ! did_action( 'customize_preview_init' ) ) {
- $wp_customize->customize_preview_init();
- }
-
- // Note that using $pagenow is easier to test vs DOING_AJAX.
- if ( ! empty( $pagenow ) && 'admin-ajax.php' === $pagenow ) {
- $this->override_request_method();
- } else {
- add_action( 'parse_request', array( $this, 'override_request_method' ), 5 );
- }
-
- $wp_customize->remove_preview_signature();
- }
-
- /**
- * Attempt to convert the current request environment into another environment.
- *
- * @global \WP $wp
- *
- * @return bool Whether the override was applied.
- */
- public function override_request_method() {
- global $wp;
-
- // Skip of X-HTTP-Method-Override request header is not present.
- if ( ! isset( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) || ! isset( $_SERVER['REQUEST_METHOD'] ) ) { // WPCS: input var ok.
- return false;
- }
-
- // Skip if REST API request since it has built-in support for overriding the request method.
- if ( ! empty( $wp ) && ! empty( $wp->query_vars['rest_route'] ) ) {
- return false;
- }
-
- // Skip if the request method is not GET or POST, or the override is the same as the original.
- $original_request_method = strtoupper( sanitize_key( $_SERVER['REQUEST_METHOD'] ) ); // WPCS: input var ok.
- $override_request_method = strtoupper( sanitize_key( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) ); // WPCS: input var ok.
- if ( ! in_array( $override_request_method, array( 'GET', 'POST' ), true ) || $original_request_method === $override_request_method ) {
- return false;
- }
-
- // Convert a POST request into a GET request.
- if ( 'GET' === $override_request_method && 'POST' === $original_request_method ) {
- $_SERVER['REQUEST_METHOD'] = $override_request_method;
- $_GET = array_merge( $_GET, $_POST ); // WPCS: input var ok; CSRF ok.
- $_SERVER['QUERY_STRING'] = build_query( array_map( 'rawurlencode', wp_unslash( $_GET ) ) ); // WPCS: input var ok. CSRF ok.
- return true;
- }
-
- return false;
- }
-
- /**
- * Check whether customize_publish capability is granted in customize_save.
- */
- public function check_customize_publish_authorization() {
- if ( $this->doing_customize_save_ajax() && ! current_user_can( 'customize_publish' ) ) {
- wp_send_json_error( array(
- 'error' => 'customize_publish_unauthorized',
- ) );
- }
- }
-
- /**
- * Show the theme switch error if there is one.
- */
- public function show_theme_switch_error() {
- if ( empty( $this->snapshot ) ) {
- return;
- }
- $error = $this->get_theme_switch_error( $this->snapshot );
- if ( is_wp_error( $error ) ) {
- wp_die( esc_html( $error->get_error_message() ) );
- }
- }
-
- /**
- * Publish the snapshot snapshots via AJAX.
- *
- * Fires at `customize_save_after` to update and publish the snapshot.
- * The logic in here is the inverse of save_settings_with_publish_snapshot.
- *
- * @see Customize_Snapshot_Manager::save_settings_with_publish_snapshot()
- *
- * @return bool Whether the snapshot was saved successfully.
- */
- public function publish_snapshot_with_customize_save_after() {
- $that = $this;
-
- if ( ! $this->snapshot || ! $this->doing_customize_save_ajax() ) {
- return false;
- }
-
- // This should never be reached due to Customize_Snapshot_Manager::check_customize_publish_authorization().
- if ( ! current_user_can( 'customize_publish' ) ) {
- return false;
- }
-
- $settings_data = array_map(
- function( $value ) {
- return compact( 'value' );
- },
- $this->customize_manager->unsanitized_post_values()
- );
- $result = $this->snapshot->set( $settings_data, array(
- 'skip_validation' => true,
- ) );
- if ( ! empty( $result['errors'] ) ) {
- add_filter( 'customize_save_response', function( $response ) use ( $result, $that ) {
- $response['snapshot_errors'] = $that->prepare_errors_for_response( $result['errors'] );
- return $response;
- } );
- return false;
- }
-
- if ( ! $this->snapshot->post() || 'publish' !== $this->snapshot->post()->post_status ) {
- $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['date_gmt'] = current_time( 'mysql', true );
- }
-
- if ( isset( $_POST['title'] ) ) { // WPCS: input var ok. CSRF ok because customize_save_after happens after nonce check.
- $title = sanitize_text_field( wp_unslash( $_POST['title'] ) ); // WPCS: Input var ok. CSRF ok because customize_save_after happens after nonce check.
- if ( ! empty( $title ) ) {
- $args['post_title'] = $title;
- }
- }
-
- $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 );
- return $response;
- } );
- return false;
- }
- }
-
- // Send the new UUID to the client for the next snapshot.
- $class = __CLASS__; // For PHP 5.3.
- add_filter( 'customize_save_response', function( $data ) use ( $class ) {
- $data['new_customize_snapshot_uuid'] = $class::generate_uuid();
- return $data;
- } );
- return true;
- }
-
- /**
- * Publish snapshot changes when snapshot post is being published.
- *
- * The logic in here is the inverse of to publish_snapshot_with_customize_save_after.
- *
- * The meat of the logic that manipulates the post_content and validates the settings
- * needs to be done in wp_insert_post_data filter in like a
- * filter_insert_post_data_to_validate_published_snapshot method? This would
- * have the benefit of reducing one wp_insert_post() call.
- *
- * @todo Consider using wp_insert_post_data to prevent double calls to wp_insert_post().
- * @see Customize_Snapshot_Manager::publish_snapshot_with_customize_save_after()
- *
- * @param string $new_status New status.
- * @param string $old_status Old status.
- * @param \WP_Post $post Post object.
- * @return bool Whether the settings were saved.
- */
- public function save_settings_with_publish_snapshot( $new_status, $old_status, $post ) {
-
- // Abort if not transitioning a snapshot post to publish from a non-publish status.
- if ( $this->get_post_type() !== $post->post_type || 'publish' !== $new_status || $new_status === $old_status ) {
- return false;
- }
-
- $this->ensure_customize_manager();
-
- if ( $this->doing_customize_save_ajax() ) {
- // Short circuit because customize_save ajax call is changing status.
- return false;
- }
-
- // Populate customized state with values from snapshot.
- $snapshot_content = $this->post_type->get_post_content( $post );
- foreach ( $snapshot_content as $setting_id => $setting_params ) {
- if ( array_key_exists( 'value', $setting_params ) ) {
- $this->customize_manager->set_post_value( $setting_id, $setting_params['value'] );
- }
- }
-
- if ( ! did_action( 'customize_register' ) ) {
- /*
- * When running from CLI or Cron, we have to remove the action because
- * it will get added with a default priority of 10, after themes and plugins
- * have already done add_action( 'customize_register' ), resulting in them
- * being called first at the priority 10. So we manually call the
- * prerequisite function WP_Customize_Manager::register_controls() and
- * remove it from being called when the customize_register action fires.
- */
- remove_action( 'customize_register', array( $this->customize_manager, 'register_controls' ) );
- $this->customize_manager->register_controls();
-
- /*
- * Unfortunate hack to prevent \WP_Customize_Widgets::customize_register()
- * from calling preview() on settings. This needs to be cleaned up in core.
- * It is important for previewing to be prevented because if an option has
- * a filter it will short-circuit when an update is attempted since it
- * detects that there is no change to be put into the DB.
- * See: https://github.com/xwp/wordpress-develop/blob/e8c58c47db1421a1d0b2afa9ad4b9eb9e1e338e0/src/wp-includes/class-wp-customize-widgets.php#L208-L217
- */
- if ( ! defined( 'DOING_AJAX' ) ) {
- define( 'DOING_AJAX', true );
- }
- $_REQUEST['action'] = 'customize_save';
-
- /** This action is documented in wp-includes/class-wp-customize-manager.php */
- do_action( 'customize_register', $this->customize_manager );
-
- // undefine( 'DOING_AJAX' )... just kidding. This is the end of the unfortunate hack and it should be fixed in Core.
- unset( $_REQUEST['action'] ); // WPCS: Input var ok.
- }
-
- if ( method_exists( $this->customize_manager, 'validate_setting_values' ) ) {
- /** This action is documented in wp-includes/class-wp-customize-manager.php */
- do_action( 'customize_save_validation_before', $this->customize_manager );
- }
-
- $setting_ids = array_keys( $snapshot_content );
- $this->customize_manager->add_dynamic_settings( $setting_ids );
-
- /** This action is documented in wp-includes/class-wp-customize-manager.php */
- do_action( 'customize_save', $this->customize_manager );
-
- /**
- * Settings to save.
- *
- * @var \WP_Customize_Setting[]
- */
- $settings = array();
-
- $publish_error_count = 0;
- foreach ( $snapshot_content as $setting_id => &$setting_params ) {
-
- // Missing value error.
- if ( ! isset( $setting_params['value'] ) || is_null( $setting_params['value'] ) ) {
- if ( ! is_array( $setting_params ) ) {
- if ( ! empty( $setting_params ) ) {
- $setting_params = array(
- 'value' => $setting_params,
- );
- } else {
- $setting_params = array();
- }
- }
- $setting_params['publish_error'] = 'null_value';
- $publish_error_count += 1;
- continue;
- }
-
- // Unrecognized setting error.
- $setting = $this->customize_manager->get_setting( $setting_id );
- if ( ! ( $setting instanceof \WP_Customize_Setting ) ) {
- $setting_params['publish_error'] = 'unrecognized_setting';
- $publish_error_count += 1;
- continue;
- }
-
- // Validate setting value.
- if ( method_exists( $setting, 'validate' ) ) {
- $validity = $setting->validate( $setting_params['value'] );
- if ( is_wp_error( $validity ) ) {
- $setting_params['publish_error'] = $validity->get_error_code();
- $publish_error_count += 1;
- continue;
- }
- }
-
- // Validate sanitized setting value.
- $sanitized_value = $setting->sanitize( $setting_params['value'] );
- if ( is_null( $sanitized_value ) || is_wp_error( $sanitized_value ) ) {
- $setting_params['publish_error'] = is_wp_error( $sanitized_value ) ? $sanitized_value->get_error_code() : 'invalid_value';
- $publish_error_count += 1;
- continue;
- }
-
- $settings[] = $setting;
- unset( $setting_params['publish_error'] );
- } // End foreach().
-
- // Handle error scenarios.
- if ( $publish_error_count > 0 ) {
- $update_setting_args = array(
- 'ID' => $post->ID,
- 'post_content' => Customize_Snapshot_Manager::encode_json( $snapshot_content ),
- 'post_status' => 'pending',
- );
- wp_update_post( wp_slash( $update_setting_args ) );
- update_post_meta( $post->ID, 'snapshot_error_on_publish', $publish_error_count );
-
- add_filter( 'redirect_post_location', function( $location ) {
- $location = add_query_arg( 'snapshot_error_on_publish', '1', $location );
- return $location;
- } );
- return false;
- }
-
- /*
- * Change all setting capabilities temporarily to 'exist' to allow them to
- * be saved regardless of current user, such as when WP-Cron is publishing
- * the snapshot post if it was scheduled. It is safe to do this because
- * a setting can only be written into a snapshot by users who have the
- * capability, so after it has been added to a snapshot it is good to commit.
- */
- $existing_caps = wp_list_pluck( $settings, 'capability' );
- foreach ( $settings as $setting ) {
- $setting->capability = 'exist';
- }
-
- // Persist the settings in the DB.
- foreach ( $settings as $setting ) {
- $setting->save();
- }
-
- // Restore setting capabilities.
- foreach ( $existing_caps as $setting_id => $existing_cap ) {
- $settings[ $setting_id ]->capability = $existing_cap;
- }
-
- /** This action is documented in wp-includes/class-wp-customize-manager.php */
- do_action( 'customize_save_after', $this->customize_manager );
-
- // Remove any previous error on setting.
- delete_post_meta( $post->ID, 'snapshot_error_on_publish' );
-
- return true;
- }
-
- /**
- * Update snapshots via AJAX.
- */
- public function handle_update_snapshot_request() {
- if ( ! check_ajax_referer( self::AJAX_ACTION, 'nonce', false ) ) {
- status_header( 400 );
- wp_send_json_error( 'bad_nonce' );
- } elseif ( ! current_user_can( 'customize' ) ) {
- status_header( 403 );
- wp_send_json_error( 'customize_not_allowed' );
- } elseif ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== $_SERVER['REQUEST_METHOD'] ) { // WPCS: input var ok.
- status_header( 405 );
- wp_send_json_error( 'bad_method' );
- } elseif ( empty( $this->current_snapshot_uuid ) ) {
- status_header( 400 );
- wp_send_json_error( 'invalid_customize_snapshot_uuid' );
- } elseif ( 0 === count( $this->customize_manager->unsanitized_post_values() ) ) {
- status_header( 400 );
- wp_send_json_error( 'missing_snapshot_customized' );
- }
-
- if ( isset( $_POST['status'] ) ) { // WPCS: input var ok.
- $status = sanitize_key( $_POST['status'] ); // WPCS: input var ok.
- } else {
- $status = 'draft';
- }
- if ( ! in_array( $status, array( 'draft', 'pending', 'future' ), true ) ) {
- status_header( 400 );
- wp_send_json_error( 'bad_status' );
- }
- if ( 'future' === $status && ! current_user_can( 'customize_publish' ) ) {
- status_header( 400 );
- wp_send_json_error( 'customize_not_allowed' );
- }
- $publish_date = isset( $_POST['date'] ) ? sanitize_text_field( wp_unslash( $_POST['date'] ) ) : ''; // WPCS: input var ok.
- if ( 'future' === $status ) {
- $publish_date_obj = new \DateTime( $publish_date );
- $current_date = new \DateTime( current_time( 'mysql' ) );
- if ( empty( $publish_date ) || ! $publish_date_obj || $current_date > $publish_date_obj ) {
- status_header( 400 );
- wp_send_json_error( 'bad_schedule_time' );
- }
- }
-
- // Prevent attempting to modify a "locked" snapshot (a published one).
- $post = $this->snapshot->post();
- if ( $post && 'publish' === $post->post_status ) {
- wp_send_json_error( array(
- 'errors' => array(
- 'already_published' => array(
- 'message' => __( 'The snapshot has already published so it is locked.', 'customize-snapshots' ),
- ),
- ),
- ) );
- }
-
- /**
- * Add any additional checks before saving snapshot.
- *
- * @param Customize_Snapshot $snapshot Snapshot to be saved.
- * @param Customize_Snapshot_Manager $snapshot_manager Snapshot manager.
- */
- do_action( 'customize_snapshot_save_before', $this->snapshot, $this );
-
- // Set the snapshot UUID.
- $post_type = get_post_type_object( $this->get_post_type() );
- $authorized = ( $post ?
- current_user_can( $post_type->cap->edit_post, $post->ID ) :
- current_user_can( 'customize' )
- );
- if ( ! $authorized ) {
- status_header( 403 );
- wp_send_json_error( 'unauthorized' );
- }
-
- $data = array(
- 'errors' => null,
- );
- $settings_data = array_map(
- function( $value ) {
- return compact( 'value' );
- },
- $this->customize_manager->unsanitized_post_values()
- );
- $r = $this->snapshot->set( $settings_data );
- if ( method_exists( $this->customize_manager, 'prepare_setting_validity_for_js' ) ) {
- $data['setting_validities'] = array_map(
- array( $this->customize_manager, 'prepare_setting_validity_for_js' ),
- $r['validities']
- );
- }
-
- if ( $r['errors'] ) {
- $data['errors'] = $this->prepare_errors_for_response( $r['errors'] );
- wp_send_json_error( $data );
- }
- $args = array(
- 'status' => $status,
- );
- if ( isset( $_POST['title'] ) ) { // WPCS: input var ok.
- $title = sanitize_text_field( wp_unslash( $_POST['title'] ) ); // WPCS: input var ok.
- if ( '' !== $title ) {
- $args['post_title'] = $title;
- }
- }
-
- if ( isset( $publish_date_obj ) && 'future' === $status ) {
- $args['date_gmt'] = get_gmt_from_date( $publish_date_obj->format( 'Y-m-d H:i:s' ) );
- }
- $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;
- $data['title'] = $post->post_title;
- }
-
- if ( is_wp_error( $r ) ) {
- $data['errors'] = $this->prepare_errors_for_response( $r );
- wp_send_json_error( $data );
- }
-
- /** This filter is documented in wp-includes/class-wp-customize-manager.php */
- $data = apply_filters( 'customize_save_response', $data, $this->customize_manager );
- wp_send_json_success( $data );
- }
-
- /**
- * Set up Customizer preview.
- */
- public function customize_preview_init() {
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
- }
-
- /**
- * Enqueue Customizer preview scripts.
- *
- * @global \WP_Customize_Manager $wp_customize
- */
- public function enqueue_preview_scripts() {
- global $wp_customize;
-
- $handle = 'customize-snapshots-preview';
- wp_enqueue_script( $handle );
- wp_enqueue_style( $handle );
-
- $exports = array(
- 'home_url' => wp_parse_url( home_url( '/' ) ),
- 'rest_api_url' => wp_parse_url( rest_url( '/' ) ),
- 'admin_ajax_url' => wp_parse_url( admin_url( 'admin-ajax.php' ) ),
- 'initial_dirty_settings' => array_keys( $wp_customize->unsanitized_post_values() ),
- );
- wp_add_inline_script(
- $handle,
- sprintf( 'CustomizeSnapshotsPreview.init( %s )', wp_json_encode( $exports ) ),
- 'after'
- );
- }
-
- /**
- * Enqueue Customizer frontend scripts.
- */
- public function enqueue_frontend_scripts() {
- if ( ! $this->snapshot || is_customize_preview() ) {
- return;
- }
- $handle = 'customize-snapshots-frontend';
- wp_enqueue_script( $handle );
-
- $exports = array(
- 'uuid' => $this->snapshot ? $this->snapshot->uuid() : null,
- 'home_url' => wp_parse_url( home_url( '/' ) ),
- 'l10n' => array(
- 'restoreSessionPrompt' => __( 'It seems you may have inadvertently navigated away from previewing a customized state. Would you like to restore the snapshot context?', 'customize-snapshots' ),
- ),
- );
- wp_add_inline_script(
- $handle,
- sprintf( 'CustomizeSnapshotsFrontend.init( %s )', wp_json_encode( $exports ) ),
- 'after'
- );
- }
-
- /**
- * Underscore (JS) templates.
- */
- public function render_templates() {
- $this->add_edit_box_template();
- ?>
-
-
-
-
-
-
-
-
-
- get_customize_manager()->changeset_post_id();
+ if ( $post_id ) {
+ $post = get_post( $post_id );
+ $preview_url_query_vars = $this->post_type->get_customizer_state_query_vars( $post->ID );
+ if ( $post instanceof \WP_Post ) {
+ $this->override_post_date_default_data( $post );
+ $edit_link = $this->get_edit_link( $post_id );
+ }
+ }
+
+ // Script data array.
+ $exports = apply_filters( 'customize_snapshots_export_data', array(
+ 'editLink' => isset( $edit_link ) ? $edit_link : '',
+ 'publishDate' => isset( $post->post_date ) ? $post->post_date : '',
+ 'title' => isset( $post->post_title ) ? $post->post_title : '',
+ 'postStatus' => isset( $post->post_status ) ? $post->post_status : '',
+ 'currentUserCanPublish' => current_user_can( 'customize_publish' ),
+ 'initialServerDate' => current_time( 'mysql', false ),
+ 'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
+ 'previewingTheme' => isset( $preview_url_query_vars['theme'] ) ? $preview_url_query_vars['theme'] : '',
+ 'i18n' => array(
+ 'saveButton' => __( 'Save', 'customize-snapshots' ),
+ 'updateButton' => __( 'Update', 'customize-snapshots' ),
+ 'submit' => __( 'Submit', 'customize-snapshots' ),
+ 'submitted' => __( 'Submitted', 'customize-snapshots' ),
+ 'permsMsg' => array(
+ 'save' => __( 'You do not have permission to publish changes, but you can create a changeset by clicking the "Save" button.', 'customize-snapshots' ),
+ 'update' => __( 'You do not have permission to publish changes, but you can modify this changeset by clicking the "Update" button.', 'customize-snapshots' ),
+ ),
+ 'aysMsg' => __( 'Changes that you made may not be saved.', 'customize-snapshots' ),
+ 'errorMsg' => __( 'The changeset could not be saved.', 'customize-snapshots' ),
+ 'errorTitle' => __( 'Error', 'customize-snapshots' ),
+ 'collapseSnapshotScheduling' => __( 'Collapse changeset scheduling', 'customize-snapshots' ),
+ 'expandSnapshotScheduling' => __( 'Expand changeset scheduling', 'customize-snapshots' ),
+ ),
+ ) );
+
+ wp_scripts()->add_inline_script(
+ 'customize-snapshots',
+ sprintf( 'wp.customize.snapshots = new wp.customize.Snapshots( %s );', wp_json_encode( $exports ) ),
+ 'after'
+ );
+ }
+
+ /**
+ * Underscore (JS) templates for dialog windows.
+ */
+ public function render_templates() {
+ $this->add_edit_box_template();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+ get_month_choices();
+ ?>
+
+
+
+ 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-customize-snapshot-manager.php b/php/class-customize-snapshot-manager.php
index f905c43c..0efeeec2 100644
--- a/php/class-customize-snapshot-manager.php
+++ b/php/class-customize-snapshot-manager.php
@@ -16,13 +16,6 @@
*/
class Customize_Snapshot_Manager {
- /**
- * Action nonce.
- *
- * @type string
- */
- const AJAX_ACTION = 'customize_update_snapshot';
-
/**
* Plugin instance.
*
@@ -33,49 +26,10 @@ class Customize_Snapshot_Manager {
/**
* Post type.
*
- * @var Post_Type|Post_Type_Back_Compat
+ * @var Post_Type
*/
public $post_type;
- /**
- * Customize_Snapshot instance.
- *
- * @todo Rename `Customize_Snapshot` to just `Snapshot`.
- *
- * @var Customize_Snapshot|Customize_Snapshot_Back_Compat
- */
- public $snapshot;
-
- /**
- * Customize manager.
- *
- * @var \WP_Customize_Manager
- */
- public $customize_manager;
-
- /**
- * Snapshot UUID for the current request.
- *
- * @access public
- * @var string
- */
- public $current_snapshot_uuid;
-
- /**
- * Whether the snapshot settings are being previewed.
- *
- * @var bool
- */
- protected $previewing_settings = false;
-
- /**
- * The originally active theme.
- *
- * @access public
- * @var string
- */
- public $original_stylesheet;
-
/**
* Constructor.
*
@@ -85,7 +39,6 @@ class Customize_Snapshot_Manager {
*/
public function __construct( Plugin $plugin ) {
$this->plugin = $plugin;
- $this->original_stylesheet = get_stylesheet();
}
/**
@@ -99,17 +52,19 @@ function hooks() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
+ add_action( 'load-edit.php', array( $this, 'handle_frontend_changeset_publish' ) );
+
add_action( 'customize_controls_init', array( $this, 'add_snapshot_uuid_to_return_url' ) );
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_templates' ) );
add_action( 'admin_bar_menu', array( $this, 'customize_menu' ), 41 );
add_action( 'admin_bar_menu', array( $this, 'remove_all_non_snapshot_admin_bar_links' ), 100000 );
add_action( 'wp_before_admin_bar_render', array( $this, 'print_admin_bar_styles' ) );
- add_filter( 'removable_query_args', array( $this, 'filter_removable_query_args' ) );
add_action( 'save_post_' . $this->get_post_type(), array( $this, 'create_initial_changeset_revision' ) );
add_action( 'save_post_' . $this->get_post_type(), array( $this, 'save_customizer_state_query_vars' ) );
add_filter( 'wp_insert_post_data', array( $this, 'prepare_snapshot_post_content_for_publish' ) );
remove_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
add_action( 'delete_post', array( $this, 'clean_up_nav_menus_created_auto_drafts' ) );
+ add_filter( 'customize_save_response', array( $this, 'add_snapshot_var_to_customize_save' ), 10, 2 );
}
/**
@@ -118,18 +73,6 @@ function hooks() {
function init() {
$this->post_type = new Post_Type( $this );
$this->hooks();
- add_filter( 'customize_save_response', array( $this, 'add_snapshot_var_to_customize_save' ), 10, 2 );
- if ( $this->read_current_snapshot_uuid() ) {
- $this->load_snapshot();
- }
- }
-
- /**
- * Load Snapshot.
- */
- public function load_snapshot() {
- $this->ensure_customize_manager();
- $this->snapshot = new Customize_Snapshot( $this );
}
/**
@@ -142,104 +85,78 @@ public function load_snapshot() {
*/
public function add_snapshot_var_to_customize_save( $response, $customize_manager ) {
$changeset_post = get_post( $customize_manager->changeset_post_id() );
- $response['edit_link'] = $this->snapshot->get_edit_link( $changeset_post->ID );
- $response['publish_date'] = $changeset_post->post_date;
+ $response['edit_link'] = $this->get_edit_link( $changeset_post->ID );
+ $response['publish_date'] = $changeset_post->post_date; // @todo Remove when drop support for < 4.9.
$response['title'] = $changeset_post->post_title;
return $response;
}
/**
- * Read the current snapshot UUID from the request.
+ * Get edit post link.
+ *
+ * @param int|\WP_Post $post_id Post.
*
- * @returns bool Whether a valid snapshot was read.
+ * @return null|string Post edit link.
*/
- public function read_current_snapshot_uuid() {
- $customize_arg = $this->get_customize_uuid_param();
- $frontend_arg = $this->get_front_uuid_param();
- $uuid = null;
- if ( isset( $_REQUEST[ $customize_arg ] ) ) { // WPCS: input var ok. CSRF ok.
- $uuid = sanitize_key( wp_unslash( $_REQUEST[ $customize_arg ] ) ); // WPCS: input var ok. CSRF ok.
- } elseif ( isset( $_REQUEST[ $frontend_arg ] ) ) { // WPCS: input var ok. CSRF ok.
- $uuid = sanitize_key( wp_unslash( $_REQUEST[ $frontend_arg ] ) ); // WPCS: input var ok. CSRF ok.
+ public function get_edit_link( $post_id ) {
+ $has_filter = has_filter( 'get_edit_post_link', '__return_empty_string' );
+ if ( $has_filter ) {
+ remove_filter( 'get_edit_post_link', '__return_empty_string' );
}
-
- if ( $uuid && static::is_valid_uuid( $uuid ) ) {
- $this->current_snapshot_uuid = $uuid;
- return true;
+ $link = get_edit_post_link( $post_id, 'raw' );
+ if ( $has_filter ) {
+ add_filter( 'get_edit_post_link', '__return_empty_string' );
}
- $this->current_snapshot_uuid = null;
- return false;
+ return $link;
}
/**
- * Return true if it's a customize_save Ajax request.
+ * Get the customize manager.
*
- * @return bool True if it's an Ajax request, false otherwise.
+ * @return \WP_Customize_Manager Manager.
*/
- public function doing_customize_save_ajax() {
- return isset( $_REQUEST['action'] ) && sanitize_key( wp_unslash( $_REQUEST['action'] ) ) === 'customize_save'; // WPCS: input var ok. CSRF ok.
+ function get_customize_manager() {
+ global $wp_customize;
+ return $wp_customize;
}
/**
* Ensure Customizer manager is instantiated.
*
* @global \WP_Customize_Manager $wp_customize
+ * @return \WP_Customize_Manager Manager.
*/
public function ensure_customize_manager() {
global $wp_customize;
+
+ $args = array();
if ( empty( $wp_customize ) || ! ( $wp_customize instanceof \WP_Customize_Manager ) ) {
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- if ( null !== $this->current_snapshot_uuid ) {
- $wp_customize = new \WP_Customize_Manager( array(
- 'changeset_uuid' => $this->current_snapshot_uuid,
- ) ); // WPCS: override ok.
- } else {
- $wp_customize = new \WP_Customize_Manager(); // WPCS: override ok.
- }
+ $wp_customize = new \WP_Customize_Manager( $args ); // WPCS: override ok.
}
- $this->customize_manager = $wp_customize;
- }
-
- /**
- * Is previewing another theme.
- *
- * @return bool Whether theme is active.
- *
- * @deprecated in favor of WP_Customize_Manager::is_theme_active()
- * @todo move to back compat?
- */
- public function is_theme_active() {
- if ( empty( $this->customize_manager ) ) {
- return true;
- }
- return $this->customize_manager->get_stylesheet() === $this->original_stylesheet;
+ return $wp_customize;
}
/**
* Add snapshot UUID the Customizer return URL.
*
- * If the Customizer was loaded with a snapshot UUID, let the return URL include this snapshot.
- *
- * @todo move to back compat?
+ * If the Customizer was loaded from a referring URL had a changeset UUID, then ensure the return URL also includes this param.
*/
public function add_snapshot_uuid_to_return_url() {
+ $wp_customize = $this->get_customize_manager();
$should_add_snapshot_uuid = (
- isset( $_GET[ $this->get_front_uuid_param() ] )
- &&
- $this->current_snapshot_uuid
- &&
- $this->customize_manager->is_theme_active()
+ is_customize_preview()
&&
- false === strpos( $this->customize_manager->get_return_url(), '/wp-admin/' )
+ false !== strpos( parse_url( wp_get_referer(), PHP_URL_QUERY ), 'customize_changeset_uuid=' . $wp_customize->changeset_uuid() )
);
if ( $should_add_snapshot_uuid ) {
$args_name = $this->get_front_uuid_param();
$args = array(
- $args_name => $this->current_snapshot_uuid,
+ $args_name => $wp_customize->changeset_uuid(),
);
- $return_url = add_query_arg( array_map( 'rawurlencode', $args ), $this->customize_manager->get_return_url() );
- $this->customize_manager->set_return_url( $return_url );
+ $return_url = add_query_arg( array_map( 'rawurlencode', $args ), $wp_customize->get_return_url() );
+ $this->get_customize_manager()->set_return_url( $return_url );
}
}
@@ -267,54 +184,37 @@ static public function encode_json( $value ) {
* @global \WP_Customize_Manager $wp_customize
*/
public function enqueue_controls_scripts() {
- $this->ensure_customize_manager();
-
wp_enqueue_style( 'customize-snapshots' );
wp_enqueue_script( 'customize-snapshots' );
$post = null;
+ $preview_url_query_vars = array();
+ $post_id = $this->get_customize_manager()->changeset_post_id();
- if ( $this->snapshot ) {
- $post_id = $this->customize_manager->changeset_post_id();
+ if ( $post_id ) {
$post = get_post( $post_id );
$preview_url_query_vars = $this->post_type->get_customizer_state_query_vars( $post->ID );
if ( $post instanceof \WP_Post ) {
- $this->override_post_date_default_data( $post );
- $edit_link = $this->snapshot->get_edit_link( $post );
+ $edit_link = $this->get_edit_link( $post_id );
}
}
// Script data array.
$exports = apply_filters( 'customize_snapshots_export_data', array(
- 'editLink' => isset( $edit_link ) ? $edit_link : '',
- 'publishDate' => isset( $post->post_date ) ? $post->post_date : '',
+ 'inspectLink' => isset( $edit_link ) ? $edit_link : '',
'title' => isset( $post->post_title ) ? $post->post_title : '',
- 'postStatus' => isset( $post->post_status ) ? $post->post_status : '',
- 'currentUserCanPublish' => current_user_can( 'customize_publish' ),
- 'initialServerDate' => current_time( 'mysql', false ),
- 'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
'previewingTheme' => isset( $preview_url_query_vars['theme'] ) ? $preview_url_query_vars['theme'] : '',
'i18n' => array(
- 'saveButton' => __( 'Save', 'customize-snapshots' ),
- 'updateButton' => __( 'Update', 'customize-snapshots' ),
- 'submit' => __( 'Submit', 'customize-snapshots' ),
- 'submitted' => __( 'Submitted', 'customize-snapshots' ),
- 'permsMsg' => array(
- 'save' => __( 'You do not have permission to publish changes, but you can create a changeset by clicking the "Save" button.', 'customize-snapshots' ),
- 'update' => __( 'You do not have permission to publish changes, but you can modify this changeset by clicking the "Update" button.', 'customize-snapshots' ),
- ),
- 'aysMsg' => __( 'Changes that you made may not be saved.', 'customize-snapshots' ),
- 'errorMsg' => __( 'The changeset could not be saved.', 'customize-snapshots' ),
- 'errorTitle' => __( 'Error', 'customize-snapshots' ),
- 'collapseSnapshotScheduling' => __( 'Collapse changeset scheduling', 'customize-snapshots' ),
- 'expandSnapshotScheduling' => __( 'Expand changeset scheduling', 'customize-snapshots' ),
+ 'title' => __( 'Title', 'customize-snapshots' ),
+ 'savePending' => __( 'Save Pending', 'customize-snapshots' ),
+ 'pendingSaved' => __( 'Pending Saved', 'customize-snapshots' ),
),
) );
wp_scripts()->add_inline_script(
'customize-snapshots',
- sprintf( 'var _customizeSnapshotsSettings = %s;', wp_json_encode( $exports ) ),
- 'before'
+ sprintf( 'wp.customize.snapshots = new wp.customize.Snapshots( %s );', wp_json_encode( $exports ) ),
+ 'after'
);
}
@@ -347,18 +247,19 @@ public function enqueue_admin_scripts( $hook ) {
* Enqueue Customizer frontend scripts.
*/
public function enqueue_frontend_scripts() {
- if ( ! current_user_can( 'customize' ) ) {
+ if ( ! is_customize_preview() || ! current_user_can( 'customize' ) ) {
return;
}
$handle = 'customize-snapshots-frontend';
wp_enqueue_script( $handle );
$exports = array(
- 'uuid' => $this->snapshot ? $this->snapshot->uuid() : null,
+ 'uuid' => $this->get_customize_manager()->changeset_uuid(),
'home_url' => wp_parse_url( home_url( '/' ) ),
'l10n' => array(
'restoreSessionPrompt' => __( 'It seems you may have inadvertently navigated away from previewing a customized state. Would you like to restore the changeset context?', 'customize-snapshots' ),
),
+ 'confirmationMsg' => __( 'Are you sure that you want to publish the Changeset?', 'customize-snapshots' ),
);
wp_add_inline_script(
$handle,
@@ -367,15 +268,6 @@ public function enqueue_frontend_scripts() {
);
}
- /**
- * Get the Customize_Snapshot instance.
- *
- * @return Customize_Snapshot
- */
- public function snapshot() {
- return $this->snapshot;
- }
-
/**
* Create initial changeset revision.
*
@@ -437,17 +329,6 @@ public function prepare_snapshot_post_content_for_publish( $data ) {
return $data;
}
- /**
- * Add snapshot_error_on_publish to removable_query_args.
- *
- * @param array $query_args Query args.
- * @return array Removable query args.
- */
- public function filter_removable_query_args( $query_args ) {
- $query_args[] = 'snapshot_error_on_publish';
- return $query_args;
- }
-
/**
* Prepare a WP_Error for sending to JS.
*
@@ -465,24 +346,11 @@ public function prepare_errors_for_response( \WP_Error $error ) {
return $exported_errors;
}
- /**
- * Generate a snapshot uuid.
- *
- * @return string
- */
- static public function generate_uuid() {
- return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
- mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
- mt_rand( 0, 0xffff ),
- mt_rand( 0, 0x0fff ) | 0x4000,
- mt_rand( 0, 0x3fff ) | 0x8000,
- mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
- );
- }
-
/**
* Determine whether the supplied UUID is in the right format.
*
+ * @todo Use wp_is_uuid().
+ *
* @param string $uuid Snapshot UUID.
*
* @return bool
@@ -502,6 +370,7 @@ public function customize_menu( $wp_admin_bar ) {
$this->add_changesets_admin_bar_link( $wp_admin_bar );
$this->add_resume_snapshot_link( $wp_admin_bar );
$this->add_post_edit_screen_link( $wp_admin_bar );
+ $this->add_publish_changeset_link( $wp_admin_bar );
$this->add_snapshot_exit_link( $wp_admin_bar );
}
@@ -523,6 +392,10 @@ public function print_admin_bar_styles() {
content: "\f179";
top: 2px;
}
+ #wpadminbar #wp-admin-bar-publish-customize-changeset > .ab-item:before {
+ content: "\f147";
+ top: 2px;
+ }
#wpadminbar #wp-admin-bar-exit-customize-snapshot > .ab-item:before {
content: "\f158";
top: 2px;
@@ -538,7 +411,7 @@ public function print_admin_bar_styles() {
* @param \WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
*/
public function replace_customize_link( $wp_admin_bar ) {
- if ( empty( $this->snapshot ) ) {
+ if ( ! is_customize_preview() ) {
return;
}
@@ -560,14 +433,15 @@ public function replace_customize_link( $wp_admin_bar ) {
);
}
+ $wp_customize = $this->get_customize_manager();
$args = array(
- $this->get_customize_uuid_param() => $this->current_snapshot_uuid,
+ $this->get_customize_uuid_param() => $wp_customize->changeset_uuid(),
);
- $post = $this->snapshot->post();
+ $post_id = $wp_customize->changeset_post_id();
- if ( $post ) {
- $customizer_state_query_vars = $this->post_type->get_customizer_state_query_vars( $post->ID );
+ if ( $post_id ) {
+ $customizer_state_query_vars = $this->post_type->get_customizer_state_query_vars( $post_id );
unset( $customizer_state_query_vars['url'] );
$args = array_merge( $args, $customizer_state_query_vars );
}
@@ -621,17 +495,52 @@ public function add_resume_snapshot_link( $wp_admin_bar ) {
* @param \WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
*/
public function add_post_edit_screen_link( $wp_admin_bar ) {
- if ( ! $this->snapshot ) {
+ if ( ! is_customize_preview() || ! current_user_can( get_post_type_object( $this->post_type->get_slug() )->cap->edit_posts ) ) {
return;
}
- $post = $this->snapshot->post();
- if ( ! $post ) {
+ $post_id = $this->get_customize_manager()->changeset_post_id();
+ if ( ! $post_id ) {
return;
}
$wp_admin_bar->add_menu( array(
'id' => 'inspect-customize-snapshot',
'title' => __( 'Inspect Changeset', 'customize-snapshots' ),
- 'href' => $this->snapshot->get_edit_link( $post ),
+ 'href' => $this->get_edit_link( $post_id ),
+ 'meta' => array(
+ 'class' => 'ab-item ab-customize-snapshots-item',
+ ),
+ ) );
+ }
+
+ /**
+ * Adds a "Publish Changeset" link to the Toolbar when in Snapshot mode.
+ *
+ * @param \WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
+ */
+ public function add_publish_changeset_link( $wp_admin_bar ) {
+ if ( ! is_customize_preview() || ! current_user_can( get_post_type_object( $this->post_type->get_slug() )->cap->publish_posts ) ) {
+ return;
+ }
+
+ $wp_customize = $this->get_customize_manager();
+ $post_id = $wp_customize->changeset_post_id();
+ if ( ! $post_id ) {
+ return;
+ }
+
+ $href = add_query_arg(
+ array(
+ 'post_type' => $this->post_type->get_slug(),
+ 'action' => 'frontend_publish',
+ 'uuid' => $wp_customize->changeset_uuid(),
+ 'stylesheet' => get_stylesheet(),
+ ),
+ admin_url( 'edit.php' )
+ );
+ $wp_admin_bar->add_menu( array(
+ 'id' => 'publish-customize-changeset',
+ 'title' => __( 'Publish Changeset', 'customize-snapshots' ),
+ 'href' => wp_nonce_url( $href, 'publish-changeset_' . $wp_customize->changeset_uuid() ),
'meta' => array(
'class' => 'ab-item ab-customize-snapshots-item',
),
@@ -644,7 +553,7 @@ public function add_post_edit_screen_link( $wp_admin_bar ) {
* @param \WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
*/
public function add_snapshot_exit_link( $wp_admin_bar ) {
- if ( ! $this->snapshot ) {
+ if ( ! is_customize_preview() ) {
return;
}
$wp_admin_bar->add_menu( array(
@@ -663,10 +572,15 @@ public function add_snapshot_exit_link( $wp_admin_bar ) {
* @param \WP_Admin_Bar $wp_admin_bar Admin bar.
*/
public function remove_all_non_snapshot_admin_bar_links( $wp_admin_bar ) {
- if ( empty( $this->snapshot ) ) {
+ if ( ! is_customize_preview() || ! current_user_can( 'customize' ) ) {
return;
}
- $snapshot_admin_bar_node_ids = array( 'customize', 'exit-customize-snapshot', 'inspect-customize-snapshot' );
+ $snapshot_admin_bar_node_ids = array(
+ 'customize',
+ 'exit-customize-snapshot',
+ 'inspect-customize-snapshot',
+ 'publish-customize-changeset',
+ );
foreach ( $wp_admin_bar->get_nodes() as $node ) {
if ( in_array( $node->id, $snapshot_admin_bar_node_ids, true ) || '#' === substr( $node->href, 0, 1 ) ) {
continue;
@@ -691,185 +605,15 @@ public function remove_all_non_snapshot_admin_bar_links( $wp_admin_bar ) {
* Underscore (JS) templates for dialog windows.
*/
public function render_templates() {
- $this->add_edit_box_template();
?>
-
-
-
-
-
-
-
-
-
- get_month_choices();
- ?>
-
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;
- }
-
/**
* Get Post_Type from dynamic class.
*
* @return string Post type.
*/
public function get_post_type() {
- return constant( get_class( $this->post_type ) . '::SLUG' );
+ return Post_Type::SLUG;
}
/**
@@ -986,7 +658,7 @@ public function get_post_type() {
* @return string param.
*/
public function get_front_uuid_param() {
- return constant( get_class( $this->post_type ) . '::FRONT_UUID_PARAM_NAME' );
+ return Post_Type::FRONT_UUID_PARAM_NAME;
}
/**
@@ -995,7 +667,98 @@ public function get_front_uuid_param() {
* @return string customize param name.
*/
public function get_customize_uuid_param() {
- return constant( get_class( $this->post_type ) . '::CUSTOMIZE_UUID_PARAM_NAME' );
+ return Post_Type::CUSTOMIZE_UUID_PARAM_NAME;
+ }
+
+ /**
+ * Handles request to publish changeset from frontend.
+ */
+ public function handle_frontend_changeset_publish() {
+
+ if ( ! isset( $_GET['uuid'] ) || ! isset( $_GET['action'] ) || 'frontend_publish' !== $_GET['action'] ) {
+ return;
+ }
+ $uuid = sanitize_key( wp_unslash( $_GET['uuid'] ) );
+ if ( ! static::is_valid_uuid( $uuid ) ) {
+ return;
+ }
+
+ $is_user_authorized = (
+ check_ajax_referer( 'publish-changeset_' . $uuid, false, false )
+ &&
+ current_user_can( get_post_type_object( $this->post_type->get_slug() )->cap->publish_posts )
+ );
+ if ( ! $is_user_authorized ) {
+ wp_die(
+ esc_html__( 'Oops. Unable to publish the changeset due to an expired user session. Please go back, reload the page, and try publishing again.', 'customize-snapshots' ),
+ esc_html__( 'Changeset publishing failed', 'customize-snapshots' ),
+ array(
+ 'back_link' => true,
+ 'response' => 401,
+ )
+ );
+ }
+
+ $stylesheet = null;
+ if ( isset( $_GET['stylesheet'] ) ) {
+ $theme = wp_get_theme( wp_unslash( $_GET['stylesheet'] ) );
+ if ( $theme->errors() ) {
+ $msg = __( 'Oops. Unable to publish the changeset. The following error(s) occurred: ', 'customize-snapshots' );
+ $msg .= join( '; ', array_keys( $theme->errors()->errors ) );
+ wp_die(
+ '
' . esc_html( $msg ) . '
',
+ esc_html__( 'Changeset publishing failed', 'customize-snapshots' ),
+ array(
+ 'back_link' => true,
+ 'response' => 400,
+ )
+ );
+ }
+ $stylesheet = $theme->get_stylesheet();
+ }
+
+ $wp_customize = $this->get_customize_manager();
+ $args = array();
+ if ( empty( $wp_customize ) || ! ( $wp_customize instanceof \WP_Customize_Manager ) ) {
+ require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
+ $args['changeset_uuid'] = $uuid;
+ if ( $stylesheet ) {
+ $args['theme'] = $stylesheet;
+ }
+ $wp_customize = new \WP_Customize_Manager( $args ); // WPCS: override ok.
+ }
+ $r = $wp_customize->save_changeset_post( array(
+ 'status' => 'publish',
+ ) );
+
+ if ( is_wp_error( $r ) ) {
+ $msg = __( 'Oops. Unable to publish the changeset. The following error(s) occurred: ', 'customize-snapshots' );
+ $msg .= join( '; ', array_keys( $r->errors ) );
+ wp_die(
+ '
' . esc_html( $msg ) . '
',
+ esc_html__( 'Changeset publishing failed', 'customize-snapshots' ),
+ array(
+ 'back_link' => true,
+ 'response' => 500,
+ )
+ );
+ } else {
+ $referer = wp_get_referer();
+
+ // Ensure redirect is set to frontend.
+ if ( empty( $referer ) || false !== strpos( parse_url( $referer, PHP_URL_PATH ), '/wp-admin/' ) ) {
+ $referer = home_url();
+ }
+
+ $sendback = remove_query_arg( array(
+ $this->get_front_uuid_param(),
+ 'customize_theme',
+ $this->get_customize_uuid_param(),
+ ), $referer );
+
+ wp_redirect( $sendback );
+ exit();
+ }
}
/**
@@ -1036,7 +799,7 @@ public function clean_up_nav_menus_created_auto_drafts( $changeset_post_id ) {
}
remove_action( 'delete_post', array( $this, 'clean_up_nav_menus_created_auto_drafts' ) );
foreach ( $data['nav_menus_created_posts']['value'] as $nav_menu_created_post_id ) {
- if ( 'auto-draft' !== get_post_status( $nav_menu_created_post_id ) ) {
+ if ( 'auto-draft' !== get_post_status( $nav_menu_created_post_id ) && 'draft' !== get_post_status( $nav_menu_created_post_id ) ) {
continue;
}
diff --git a/php/class-customize-snapshot.php b/php/class-customize-snapshot.php
deleted file mode 100644
index 357607e7..00000000
--- a/php/class-customize-snapshot.php
+++ /dev/null
@@ -1,83 +0,0 @@
-snapshot_manager = $snapshot_manager;
- }
-
- /**
- * Get the snapshot post associated with the provided UUID, or null if it does not exist.
- *
- * @return \WP_Post|null Post or null.
- */
- public function post() {
- $post_id = $this->snapshot_manager->customize_manager->changeset_post_id();
- if ( $post_id ) {
- return get_post( $post_id );
- }
- return null;
- }
-
- /**
- * Get the snapshot uuid.
- *
- * @return string
- */
- public function uuid() {
- return $this->snapshot_manager->customize_manager->changeset_uuid();
- }
-
- /**
- * Get edit post link.
- *
- * @param int|\WP_Post $post_id Post.
- *
- * @return null|string Post edit link.
- */
- public function get_edit_link( $post_id ) {
- $has_filter = has_filter( 'get_edit_post_link', '__return_empty_string' );
- if ( $has_filter ) {
- remove_filter( 'get_edit_post_link', '__return_empty_string' );
- }
- $link = get_edit_post_link( $post_id, 'raw' );
- if ( $has_filter ) {
- add_filter( 'get_edit_post_link', '__return_empty_string' );
- }
- return $link;
- }
-
-}
diff --git a/php/class-migrate.php b/php/class-migrate.php
deleted file mode 100644
index 625c5fcc..00000000
--- a/php/class-migrate.php
+++ /dev/null
@@ -1,244 +0,0 @@
-plugin = $plugin;
- if ( ! $plugin->compat && is_admin() && is_super_admin() ) {
- $this->maybe_migrate();
- }
- }
-
- /**
- * Is already migrated or not.
- *
- * @return bool status of migration.
- */
- public function is_migrated() {
- $snapshot_migrate_option = get_option( self::KEY );
- return ! empty( $snapshot_migrate_option );
- }
-
- /**
- * Migrate if wp version is 4.7 and above.
- */
- public function maybe_migrate() {
- if ( ! $this->is_migrated() ) {
- $found_post = $this->changeset_migrate( 1, true );
- if ( empty( $found_post ) ) {
- update_option( self::KEY, 1 );
- return;
- }
- add_action( 'admin_notices', array( $this, 'show_migration_notice' ) );
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_script' ) );
- add_action( 'wp_ajax_customize_snapshot_migration', array( $this, 'handle_migrate_changeset_request' ) );
- }
- }
-
- /**
- * Migrate 20 posts at a time.
- */
- public function handle_migrate_changeset_request() {
- check_ajax_referer( 'customize-snapshot-migration', 'nonce' );
- $limit = isset( $_REQUEST['limit'] ) ? absint( $_REQUEST['limit'] ) : 20; // WPCS: input var ok.
- $found_posts = $this->changeset_migrate( $limit );
- $remaining_post = ( $found_posts < $limit ) ? 0 : $found_posts - $limit;
- $data = array(
- 'remaining_posts' => $remaining_post,
- );
- if ( ! $remaining_post ) {
- update_option( self::KEY, 1 );
- }
- wp_send_json_success( $data );
- }
-
- /**
- * Print migration javascript script.
- */
- public function enqueue_script() {
- wp_enqueue_script( 'customize-snapshot-migrate' );
- }
-
- /**
- * Show admin notice to migrate.
- */
- public function show_migration_notice() {
- ?>
-
-
- %s %s ', esc_html__( 'Click', 'customize-snapshots' ), esc_html__( 'Migration of snapshots to changesets complete!', 'customize-snapshots' ), esc_html__( 'here', 'customize-snapshots' ), esc_html__( 'to start migration.', 'customize-snapshots' ) );
- ?>
-
-
- 'customize_snapshot',
- 'no_found_rows' => false,
- 'update_post_meta_cache' => false,
- 'update_post_term_cache' => false,
- 'post_status' => array_keys( get_post_stati() ),
- 'posts_per_page' => $limit,
- 'fields' => 'ids', // We will use get_post() to fetch each posts.
- );
-
- if ( -1 === $limit ) {
- $arg['no_found_rows'] = true;
- }
-
- $query->query( $arg );
- if ( $dry_run ) {
- return $query->posts;
- }
-
- if ( $is_doing_cli ) {
- /* translators: %s: post count.*/
- \WP_CLI::log( sprintf( __( 'Migrating %s Snapshots into Changesets', 'customize-snapshots' ), count( $query->posts ) ) );
- }
-
- if ( ! empty( $query->posts ) ) {
- $has_kses = ( false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ) );
- if ( $has_kses ) {
- kses_remove_filters(); // Prevent KSES from corrupting JSON in post_content.
- }
- if ( ! class_exists( '\WP_Customize_Manager' ) ) {
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- }
- foreach ( $query->posts as $id ) {
- $success = $this->migrate_post( $id );
- if ( $is_doing_cli ) {
- if ( $success ) {
- /* translators: %s: post id.*/
- \WP_CLI::success( sprintf( __( 'Migrated post %s.', 'customize-snapshots' ), $id ) );
- } else {
- /* translators: %s: post id.*/
- \WP_CLI::error( sprintf( __( 'Failed to migrate %s.', 'customize-snapshots' ), $id ) );
- }
- }
- }
- if ( $has_kses ) {
- kses_init_filters();
- }
- }
- if ( -1 === $limit ) {
- update_option( self::KEY, 1 );
- return count( $query->posts );
- } else {
- return $query->found_posts;
- }
- }
-
- /**
- * Migrate a post.
- *
- * @param int $id Post ID.
- * @return int|\WP_Error maybe updated.
- * @global \WP_Customize_Manager $wp_customize
- */
- public function migrate_post( $id ) {
- global $wp_customize, $wpdb;
-
- $post = get_post( $id );
-
- // Get data.
- $data = json_decode( $post->post_content, true );
- if ( json_last_error() || ! is_array( $data ) ) {
- $data = array();
- }
-
- // Get manager instance.
- $manager = new \WP_Customize_Manager();
- $original_manager = $wp_customize;
- $wp_customize = $manager; // Export to global since some filters (like widget_customizer_setting_args) lack as $wp_customize context and need global. WPCS: override ok.
-
- // Validate data.
- foreach ( $data as $setting_id => $setting_params ) {
- // Amend post values with any supplied data.
- if ( array_key_exists( 'value', $setting_params ) ) {
- $manager->set_post_value( $setting_id, $setting_params['value'] ); // Add to post values so that they can be validated and sanitized.
- }
- }
- do_action( 'customize_register', $manager );
-
- // Note that in addition to post data, this will include any stashed theme mods.
- $post_values = $manager->unsanitized_post_values( array(
- 'exclude_changeset' => true,
- 'exclude_post_data' => false,
- ) );
-
- // Update data as new changeset.
- $manager->add_dynamic_settings( array_keys( $post_values ) );
- $theme = get_post_meta( $id, '_snapshot_theme', true );
- $post_data = array();
- foreach ( $post_values as $setting_id => $setting_value ) {
- $setting = $manager->get_setting( $setting_id );
-
- if ( $setting && 'theme_mod' === $setting->type ) {
- $prefixed_setting_id = $theme . '::' . $setting->id;
- } else {
- $prefixed_setting_id = $setting_id;
- }
- $post_data[ $prefixed_setting_id ] = array(
- 'value' => $setting_value,
- 'user_id' => $post->post_author,
- );
- if ( $setting instanceof \WP_Customize_Setting ) {
- $post_data[ $prefixed_setting_id ]['type'] = $setting->type;
- }
- }
- $maybe_updated = $wpdb->update( $wpdb->posts,
- array(
- 'post_type' => 'customize_changeset',
- 'post_content' => Customize_Snapshot_Manager::encode_json( $post_data ),
- ),
- array(
- 'ID' => $post->ID,
- )
- ); // WPCS: DB call ok and cache ok, because doing update query, and using direct DB call to bypass weight of triggered hooks.
- clean_post_cache( $post );
-
- $wp_customize = $original_manager; // Restore previous manager. WPCS: override ok.
-
- return $maybe_updated;
- }
-}
diff --git a/php/class-plugin.php b/php/class-plugin.php
index cb404efd..2c2d329e 100644
--- a/php/class-plugin.php
+++ b/php/class-plugin.php
@@ -17,7 +17,7 @@ class Plugin extends Plugin_Base {
*
* @todo Rename this to just `$manager` and let the class be `Manager`.
*
- * @var Customize_Snapshot_Manager|Customize_Snapshot_Manager_Back_Compat
+ * @var Customize_Snapshot_Manager
*/
public $customize_snapshot_manager;
@@ -28,20 +28,6 @@ class Plugin extends Plugin_Base {
*/
public $version;
- /**
- * Is old version of WordPress.
- *
- * @var boolean
- */
- public $compat;
-
- /**
- * Migration handler.
- *
- * @var Migrate
- */
- public $migrate;
-
/**
* Plugin constructor.
*/
@@ -50,24 +36,13 @@ public function __construct() {
if ( preg_match( '/Version:\s*(\S+)/', file_get_contents( __DIR__ . '/../customize-snapshots.php' ), $matches ) ) { // @codingStandardsIgnoreLine because file_get_contents() is not requesting a URL.
$this->version = $matches[1];
}
- $this->compat = is_back_compat();
+
+ add_filter( 'customize_changeset_branching', '__return_true' );
load_plugin_textdomain( 'customize-snapshots' );
$this->param_back_compat();
parent::__construct();
}
- /**
- * Init migration.
- *
- * @action init
- */
- public function init_migration() {
- $this->migrate = new Migrate( $this );
- if ( defined( 'WP_CLI' ) && WP_CLI ) {
- require_once( __DIR__ . '/class-customize-snapshot-command.php' );
- }
- }
-
/**
* Initiate the plugin resources.
*
@@ -79,11 +54,7 @@ public function init_migration() {
* @action after_setup_theme, 8
*/
public function init() {
- if ( $this->compat ) {
- $this->customize_snapshot_manager = new Customize_Snapshot_Manager_Back_Compat( $this );
- } else {
- $this->customize_snapshot_manager = new Customize_Snapshot_Manager( $this );
- }
+ $this->customize_snapshot_manager = is_back_compat() ? new Customize_Snapshot_Manager_Compat( $this ) : new Customize_Snapshot_Manager( $this );
$this->customize_snapshot_manager->init();
}
@@ -99,36 +70,18 @@ public function register_scripts( \WP_Scripts $wp_scripts ) {
$min = ( SCRIPT_DEBUG || $is_git_repo ? '' : '.min' );
$handle = 'customize-snapshots';
- $src = $this->dir_url . 'js/customize-snapshots' . $min . '.js';
+ if ( version_compare( strtok( get_bloginfo( 'version' ), '-' ), '4.9', '>=' ) ) {
+ $src = $this->dir_url . 'js/customize-snapshots' . $min . '.js';
+ } else {
+ $src = $this->dir_url . 'js/customize-snapshots-compat' . $min . '.js';
+ }
$deps = array( 'jquery', 'jquery-ui-dialog', 'jquery-ui-selectmenu', 'wp-util', 'customize-controls' );
$wp_scripts->add( $handle, $src, $deps );
- if ( $this->compat ) {
- $handle = 'customize-snapshots-compat';
- $src = $this->dir_url . 'js/compat/customize-snapshots' . $min . '.js';
- $deps = array( 'customize-snapshots' );
- $wp_scripts->add( $handle, $src, $deps );
-
- $handle = 'customize-snapshots-preview';
- $src = $this->dir_url . 'js/compat/customize-snapshots-preview' . $min . '.js';
- $deps = array( 'customize-preview' );
- $wp_scripts->add( $handle, $src, $deps );
-
- $handle = 'customize-snapshots-frontend';
- $src = $this->dir_url . 'js/compat/customize-snapshots-frontend' . $min . '.js';
- $deps = array( 'jquery', 'underscore' );
- $wp_scripts->add( $handle, $src, $deps );
- } else {
- $handle = 'customize-snapshot-migrate';
- $src = $this->dir_url . 'js/customize-migrate' . $min . '.js';
- $deps = array( 'jquery', 'wp-util' );
- $wp_scripts->add( $handle, $src, $deps );
-
- $handle = 'customize-snapshots-frontend';
- $src = $this->dir_url . 'js/customize-snapshots-frontend' . $min . '.js';
- $deps = array( 'jquery', 'underscore' );
- $wp_scripts->add( $handle, $src, $deps );
- }
+ $handle = 'customize-snapshots-frontend';
+ $src = $this->dir_url . 'js/customize-snapshots-frontend' . $min . '.js';
+ $deps = array( 'jquery', 'underscore' );
+ $wp_scripts->add( $handle, $src, $deps );
$handle = 'customize-snapshots-admin';
$src = $this->dir_url . 'js/customize-snapshots-admin' . $min . '.js';
@@ -148,7 +101,11 @@ public function register_styles( \WP_Styles $wp_styles ) {
$min = ( SCRIPT_DEBUG || $is_git_repo ? '' : '.min' );
$handle = 'customize-snapshots';
- $src = $this->dir_url . 'css/customize-snapshots' . $min . '.css';
+ if ( version_compare( strtok( get_bloginfo( 'version' ), '-' ), '4.9', '>=' ) ) {
+ $src = $this->dir_url . 'css/customize-snapshots' . $min . '.css';
+ } else {
+ $src = $this->dir_url . 'css/customize-snapshots-compat' . $min . '.css';
+ }
$deps = array( 'wp-jquery-ui-dialog' );
$wp_styles->add( $handle, $src, $deps );
@@ -166,7 +123,7 @@ public function register_styles( \WP_Styles $wp_styles ) {
* Continue allowing support of param customize_snapshot_uuid in 4.7+.
*/
public function param_back_compat() {
- if ( isset( $_REQUEST['customize_snapshot_uuid'] ) && ! $this->compat ) { // WPCS: input var ok. CSRF ok.
+ if ( isset( $_REQUEST['customize_snapshot_uuid'] ) ) { // WPCS: input var ok. CSRF ok.
$_REQUEST['customize_changeset_uuid'] = $_REQUEST['customize_snapshot_uuid']; // WPCS: input var ok. CSRF ok. Sanitization ok.
$_GET['customize_changeset_uuid'] = $_REQUEST['customize_snapshot_uuid']; // WPCS: input var ok. CSRF ok. Sanitization ok.
$_POST['customize_changeset_uuid'] = $_REQUEST['customize_snapshot_uuid']; // WPCS: input var ok. CSRF ok. Sanitization ok.
diff --git a/php/class-post-type-back-compat.php b/php/class-post-type-back-compat.php
deleted file mode 100644
index 79a30083..00000000
--- a/php/class-post-type-back-compat.php
+++ /dev/null
@@ -1,241 +0,0 @@
- _x( 'Snapshots', 'post type general name', 'customize-snapshots' ),
- 'singular_name' => _x( 'Snapshot', 'post type singular name', 'customize-snapshots' ),
- 'menu_name' => _x( 'Snapshots', 'admin menu', 'customize-snapshots' ),
- 'name_admin_bar' => _x( 'Snapshot', 'add new on admin bar', 'customize-snapshots' ),
- 'add_new' => _x( 'Add New', 'Customize Snapshot', 'customize-snapshots' ),
- 'add_new_item' => __( 'Add New Snapshot', 'customize-snapshots' ),
- 'new_item' => __( 'New Snapshot', 'customize-snapshots' ),
- 'edit_item' => __( 'Inspect Snapshot', 'customize-snapshots' ),
- 'view_item' => __( 'View Snapshot', 'customize-snapshots' ),
- 'all_items' => __( 'All Snapshots', 'customize-snapshots' ),
- 'search_items' => __( 'Search Snapshots', 'customize-snapshots' ),
- 'not_found' => __( 'No snapshots found.', 'customize-snapshots' ),
- 'not_found_in_trash' => __( 'No snapshots found in Trash.', 'customize-snapshots' ),
- );
-
- $args = array(
- 'labels' => $labels,
- 'description' => __( 'Customize Snapshots.', 'customize-snapshots' ),
- 'public' => true,
- 'publicly_queryable' => false,
- 'query_var' => false,
- 'exclude_from_search' => true,
- 'show_ui' => true,
- 'show_in_nav_menus' => false,
- 'show_in_menu' => true,
- 'show_in_admin_bar' => false,
- 'map_meta_cap' => true,
- 'hierarchical' => false,
- 'delete_with_user' => false,
- 'menu_position' => null,
- 'supports' => array( 'title', 'author', 'revisions' ),
- 'capability_type' => static::SLUG,
- 'capabilities' => array(
- 'create_posts' => 'do_not_allow',
- ),
- 'rewrite' => false,
- 'show_in_customizer' => false, // Prevent inception.
- 'show_in_rest' => true,
- 'rest_base' => 'customize_snapshots',
- 'rest_controller_class' => __NAMESPACE__ . '\\Snapshot_REST_API_Controller',
- 'customize_snapshot_post_type_obj' => $this,
- 'menu_icon' => 'dashicons-camera',
- 'register_meta_box_cb' => array( $this, 'setup_metaboxes' ),
- );
-
- register_post_type( static::SLUG, $args );
-
- // Call parent hooks.
- $this->hooks();
-
- // 4.6.x and post-type specific hooks.
- add_action( 'admin_notices', array( $this, 'show_publish_error_admin_notice' ) );
- add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
- add_action( 'admin_footer-edit.php', array( $this, 'snapshot_merge_print_script' ) );
- add_action( 'load-edit.php', array( $this, 'handle_snapshot_merge_workaround' ) );
- add_filter( 'post_type_link', array( $this, 'filter_post_type_link' ), 10, 2 );
- add_filter( 'wp_insert_post_data', array( $this, 'preserve_post_name_in_insert_data' ), 10, 2 );
- }
-
- /**
- * Insert script for adding merge snapshot bulk action polyfill.
- */
- public function snapshot_merge_print_script() {
- global $post_type;
- if ( static::SLUG === $post_type ) {
- ?>
-
- current_action();
- if ( 'merge_snapshot' !== $action || ( isset( $_REQUEST['post_type'] ) && static::SLUG !== sanitize_key( wp_unslash( $_REQUEST['post_type'] ) ) ) ) { // WPCS: input var ok. CSRF ok.
- return;
- }
- if ( ! isset( $_REQUEST['post'] ) || ! is_array( $_REQUEST['post'] ) ) { // WPCS: input var ok. CSRF ok.
- return;
- }
- check_admin_referer( 'bulk-posts' );
- $post_ids = array_map( 'intval', $_REQUEST['post'] ); // WPCS: input var ok. CSRF ok.
- if ( empty( $post_ids ) ) {
- return;
- }
- $redirect_url = $this->handle_snapshot_merge( wp_get_referer(), 'merge_snapshot', $post_ids );
- if ( ! empty( $redirect_url ) ) {
- wp_safe_redirect( $redirect_url );
- exit;
- }
- }
-
- /**
- * Find a snapshot post by UUID.
- *
- * @param string $uuid UUID.
- * @return int|null Post ID or null if not found.
- */
- public function find_post( $uuid ) {
- add_action( 'pre_get_posts', array( $this, '_override_wp_query_is_single' ) );
- $query = new \WP_Query( array(
- 'name' => $uuid,
- 'posts_per_page' => 1,
- 'post_type' => static::SLUG,
- 'post_status' => get_post_stati(),
- 'no_found_rows' => true,
- 'ignore_sticky_posts' => true,
- 'cache_results' => false,
- ) );
- $posts = $query->posts;
- remove_action( 'pre_get_posts', array( $this, '_override_wp_query_is_single' ) );
-
- $post = array_shift( $posts );
- if ( $post ) {
- return $post->ID;
- } else {
- return null;
- }
- }
-
- /**
- * Preserve the post_name when submitting a snapshot for review.
- *
- * @see wp_insert_post()
- * @link https://github.com/xwp/wordpress-develop/blob/831a186108983ade4d647124d4e56e09aa254704/src/wp-includes/post.php#L3134-L3137
- *
- * @param array $post_data Post data.
- * @param array $original_post_data Original post data.
- * @return array Post data.
- */
- public function preserve_post_name_in_insert_data( $post_data, $original_post_data ) {
- if ( empty( $post_data['post_type'] ) || static::SLUG !== $post_data['post_type'] ) {
- return $post_data;
- }
- if ( empty( $post_data['post_name'] ) && 'pending' === $post_data['post_status'] ) {
- $post_data['post_name'] = $original_post_data['post_name'];
- }
- return $post_data;
- }
-
- /**
- * Display snapshot save error on post list table.
- *
- * @param array $states Display states.
- * @param \WP_Post $post Post object.
- *
- * @return mixed
- */
- public function display_post_states( $states, $post ) {
- if ( static::SLUG !== $post->post_type ) {
- return $states;
- }
- $maybe_error = get_post_meta( $post->ID, 'snapshot_error_on_publish', true );
- if ( $maybe_error ) {
- $states['snapshot_error'] = __( 'Error on publish', 'customize-snapshots' );
- }
- return $states;
- }
-
- /**
- * Show an admin notice when publishing fails and the post gets kicked back to pending.
- */
- public function show_publish_error_admin_notice() {
- if ( ! function_exists( 'get_current_screen' ) ) {
- return;
- }
- $current_screen = get_current_screen();
- if ( ! $current_screen || static::SLUG !== $current_screen->id || 'post' !== $current_screen->base ) {
- return;
- }
- if ( ! isset( $_REQUEST['snapshot_error_on_publish'] ) ) { // WPCS: input var ok. CSRF ok.
- return;
- }
- ?>
-
- snapshot_manager = $snapshot_manager;
}
+ /**
+ * Get the post type slug.
+ *
+ * @return string Post type slug.
+ */
+ public function get_slug() {
+ return static::SLUG;
+ }
+
/**
* Calls common hooks Actions and filters
*/
@@ -79,6 +88,8 @@ public function hooks() {
add_filter( 'content_save_pre', array( $this, 'filter_out_settings_if_removed_in_metabox' ), 10 );
add_action( 'admin_print_scripts-revision.php', array( $this, 'disable_revision_ui_for_published_posts' ) );
add_action( 'admin_notices', array( $this, 'admin_show_merge_error' ) );
+ add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
+ add_action( 'admin_notices', array( $this, 'show_publish_error_admin_notice' ) );
// Add workaround for failure to save changes to option settings when publishing changeset outside of customizer. See https://core.trac.wordpress.org/ticket/39221#comment:14
if ( function_exists( '_wp_customize_publish_changeset' ) && function_exists( 'wp_doing_ajax' ) ) { // Workaround only works in WP 4.7.
@@ -98,11 +109,16 @@ public function init() {
add_filter( 'post_link', array( $this, 'filter_post_type_link' ), 10, 2 );
add_action( 'add_meta_boxes_' . static::SLUG, array( $this, 'setup_metaboxes' ), 10, 1 );
- add_action( 'admin_menu',array( $this, 'add_admin_menu_item' ), 99 );
+ add_action( 'admin_menu', array( $this, 'add_admin_menu_item' ), 99 );
add_filter( 'map_meta_cap', array( $this, 'remap_customize_meta_cap' ), 5, 4 );
add_filter( 'bulk_actions-edit-' . static::SLUG, array( $this, 'add_snapshot_bulk_actions' ) );
add_filter( 'handle_bulk_actions-edit-' . static::SLUG, array( $this, 'handle_snapshot_merge' ), 10, 3 );
- add_action( 'admin_print_styles-edit.php', array( $this, 'hide_add_new_changeset_button' ) );
+ add_action( 'load-post-new.php', function() {
+ if ( static::SLUG === get_current_screen()->post_type ) {
+ wp_redirect( wp_customize_url() );
+ exit;
+ }
+ } );
}
/**
@@ -333,16 +349,17 @@ public function filter_post_row_actions( $actions, $post ) {
),
$actions
);
- } else {
- if ( isset( $actions['edit'] ) ) {
- $actions['edit'] = sprintf(
- '
%s',
- get_edit_post_link( $post->ID, 'display' ),
- /* translators: %s: post title */
- esc_attr( sprintf( __( 'View “%s”', 'customize-snapshots' ), get_the_title( $post->ID ) ) ),
- __( 'View', 'customize-snapshots' )
- );
- }
+ }
+
+ // Rename "Edit" to "Inspect" for the row action.
+ if ( isset( $actions['edit'] ) ) {
+ $actions['edit'] = sprintf(
+ '
%s',
+ get_edit_post_link( $post->ID, 'display' ),
+ /* translators: %s: post title */
+ esc_attr( sprintf( __( 'Inspect “%s”', 'customize-snapshots' ), get_the_title( $post->ID ) ) ),
+ __( 'Inspect', 'customize-snapshots' )
+ );
}
unset( $actions['inline hide-if-no-js'] );
@@ -472,8 +489,8 @@ public function render_data_metabox( $post ) {
* @return int|null Post ID or null if not found.
*/
public function find_post( $uuid ) {
- $this->snapshot_manager->ensure_customize_manager();
- return $this->snapshot_manager->customize_manager->find_changeset_post_id( $uuid );
+ $manager = $this->snapshot_manager->ensure_customize_manager();
+ return $manager->find_changeset_post_id( $uuid );
}
/**
@@ -671,6 +688,20 @@ function finish_pretending_customize_save_ajax_action( $new_status, $old_status,
*/
public function remap_customize_meta_cap( $caps, $cap ) {
$post_type_obj = get_post_type_object( static::SLUG );
+
+ /*
+ * This remap_customize_meta_cap method runs at map_meta_cap priority 5 and so here we just-in-time remove
+ * the unnecessary WP_Customize_Manager::grant_edit_post_capability_for_changeset() method added as a
+ * map_meta_cap filter with priority 10. This method is added during autosave request in
+ * WP_Customize_Manager::save_changeset_post() function in 4.9, but the logic in this
+ * remap_customize_meta_cap method in Customize Snapshots makes the core function obsolete.
+ */
+ remove_filter(
+ 'map_meta_cap',
+ array( $this->snapshot_manager->get_customize_manager(), 'grant_edit_post_capability_for_changeset' ),
+ 10
+ );
+
if ( isset( $post_type_obj->cap->$cap ) && 'customize' === $post_type_obj->cap->$cap ) {
foreach ( $caps as &$required_cap ) {
if ( 'customize' === $required_cap ) {
@@ -753,22 +784,6 @@ public function hide_disabled_publishing_actions( $post ) {
-
- save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'status' => 'draft',
'data' => $merged_snapshot_data,
'date_gmt' => gmdate( 'Y-m-d H:i:s' ),
@@ -975,7 +990,7 @@ public function set_customizer_state_query_vars( $post_id, $query_vars ) {
$stored_query_vars = array();
$autofocus_query_vars = array( 'autofocus[panel]', 'autofocus[section]', 'autofocus[control]' );
- $this->snapshot_manager->ensure_customize_manager();
+ $wp_customize = $this->snapshot_manager->ensure_customize_manager();
foreach ( wp_array_slice_assoc( $query_vars, $autofocus_query_vars ) as $key => $value ) {
if ( preg_match( '/^[a-z|\[|\]|_|\-|0-9]+$/', $value ) ) {
@@ -985,14 +1000,14 @@ public function set_customizer_state_query_vars( $post_id, $query_vars ) {
if ( ! empty( $query_vars['url'] ) && wp_validate_redirect( $query_vars['url'] ) ) {
$stored_query_vars['url'] = esc_url_raw( $query_vars['url'] );
}
- if ( isset( $query_vars['device'] ) && in_array( $query_vars['device'], array_keys( $this->snapshot_manager->customize_manager->get_previewable_devices() ), true ) ) {
+ if ( isset( $query_vars['device'] ) && in_array( $query_vars['device'], array_keys( $wp_customize->get_previewable_devices() ), true ) ) {
$stored_query_vars['device'] = $query_vars['device'];
}
if ( isset( $query_vars['scroll'] ) && is_int( $query_vars['scroll'] ) ) {
$stored_query_vars['scroll'] = $query_vars['scroll'];
}
if ( isset( $query_vars['previewing_theme'] ) ) {
- $theme = $this->snapshot_manager->customize_manager->get_stylesheet();
+ $theme = $wp_customize->get_stylesheet();
$stored_query_vars['theme'] = $query_vars['previewing_theme'] ? $theme : '';
}
update_post_meta( $post_id, '_preview_url_query_vars', $stored_query_vars );
@@ -1027,4 +1042,44 @@ public function get_frontend_view_link( $post ) {
return add_query_arg( $args, $base_url );
}
+
+ /**
+ * Display snapshot save error on post list table.
+ *
+ * @param array $states Display states.
+ * @param \WP_Post $post Post object.
+ *
+ * @return mixed
+ */
+ public function display_post_states( $states, $post ) {
+ if ( static::SLUG !== $post->post_type ) {
+ return $states;
+ }
+ $maybe_error = get_post_meta( $post->ID, 'snapshot_error_on_publish', true );
+ if ( $maybe_error ) {
+ $states['snapshot_error'] = __( 'Error on publish', 'customize-snapshots' );
+ }
+ return $states;
+ }
+
+ /**
+ * Show an admin notice when publishing fails and the post gets kicked back to pending.
+ */
+ public function show_publish_error_admin_notice() {
+ if ( ! function_exists( 'get_current_screen' ) ) {
+ return;
+ }
+ $current_screen = get_current_screen();
+ if ( ! $current_screen || static::SLUG !== $current_screen->id || 'post' !== $current_screen->base ) {
+ return;
+ }
+ if ( ! isset( $_REQUEST['snapshot_error_on_publish'] ) ) { // WPCS: input var ok. CSRF ok.
+ return;
+ }
+ ?>
+
+
0
+
+ 0
+
+
+ 0
+
0
diff --git a/readme.md b/readme.md
index 0a9186f5..1df010fd 100644
--- a/readme.md
+++ b/readme.md
@@ -6,18 +6,19 @@ Provide a UI for managing Customizer changesets; save changesets as named drafts
**Contributors:** [xwp](https://profiles.wordpress.org/xwp), [westonruter](https://profiles.wordpress.org/westonruter), [valendesigns](https://profiles.wordpress.org/valendesigns), [utkarshpatel](https://profiles.wordpress.org/utkarshpatel), [sayedwp](https://profiles.wordpress.org/sayedwp), [newscorpau](https://profiles.wordpress.org/newscorpau)
**Tags:** [customizer](https://wordpress.org/plugins/tags/customizer), [customize](https://wordpress.org/plugins/tags/customize), [changesets](https://wordpress.org/plugins/tags/changesets)
-**Requires at least:** 4.6
-**Tested up to:** 4.8.1
-**Stable tag:** 0.6.2
+**Requires at least:** 4.7
+**Tested up to:** 4.9
+**Stable tag:** 0.7.0
**License:** [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)
+**Requires PHP:** 5.3
-[![Build Status](https://travis-ci.org/xwp/wp-customize-snapshots.svg?branch=master)](https://travis-ci.org/xwp/wp-customize-snapshots) [![Coverage Status](https://coveralls.io/repos/xwp/wp-customize-snapshots/badge.svg?branch=master)](https://coveralls.io/github/xwp/wp-customize-snapshots) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com) [![devDependency Status](https://david-dm.org/xwp/wp-customize-snapshots/dev-status.svg)](https://david-dm.org/xwp/wp-customize-snapshots#info=devDependencies)
+[![Build Status](https://travis-ci.org/xwp/wp-customize-snapshots.svg?branch=master)](https://travis-ci.org/xwp/wp-customize-snapshots) [![Coverage Status](https://coveralls.io/repos/xwp/wp-customize-snapshots/badge.svg?branch=master)](https://coveralls.io/github/xwp/wp-customize-snapshots) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com) [![devDependency Status](https://david-dm.org/xwp/wp-customize-snapshots/dev-status.svg)](https://david-dm.org/xwp/wp-customize-snapshots?type=dev)
## Description ##
-Customize Snapshots is the feature plugin which prototyped [Customizer changesets](https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/); this feature was [merged](https://make.wordpress.org/core/2016/10/12/customize-changesets-formerly-transactions-merge-proposal/) as part of WordPress 4.7.
-The term “snapshots” was chosen because the Customizer feature revolved around saving the state (taking a snapshot) of the Customizer at a given time so that the changes could be saved as a draft and scheduled for future publishing.
-While the plugin's technical infrastructure for changesets was merged in WordPress 4.7,the user interface still remains largely in the Customize Snapshots plugin, in which we will continue to iterate and prototype features to merge into core.
+Customize Snapshots is the feature plugin which prototyped [Customizer changesets](https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/); this feature was [merged](https://make.wordpress.org/core/2016/10/12/customize-changesets-formerly-transactions-merge-proposal/) as part of WordPress 4.7. The term “snapshots” was chosen because the Customizer feature revolved around saving the state (taking a snapshot) of the Customizer at a given time so that the changes could be saved as a draft and scheduled for future publishing.
+
+While the plugin's technical infrastructure for changesets was merged in WordPress 4.7, the user interface still remains largely in the Customize Snapshots plugin, in which we will continue to iterate and prototype features to merge into core.
For a rundown of all the features, see the screenshots below as well as the 0.6 release video:
@@ -79,6 +80,19 @@ Requires PHP 5.3+. **Development of this plugin is done [on GitHub](https://gith
## Changelog ##
+### 0.7.0 - 2017-11-15 ###
+* Added: Add compatibility with 4.9, re-using features of the plugin that have been merged into core in this release. Increase minimum required version of WordPress to 4.7. See [#162](https://github.com/xwp/wp-customize-snapshots/pull/162).
+* Added: Remove hiding of Add New links for changesets in favor of just redirecting `post-new.php` to Customizer. See [#156](https://github.com/xwp/wp-customize-snapshots/pull/156).
+* Added: Allow publishing from preview via link in admin bar. See [#115](https://github.com/xwp/wp-customize-snapshots/pull/115), [#103](https://github.com/xwp/wp-customize-snapshots/issues/103).
+* Updated: Change link text for post list table action from “Edit” to “Inspect”. See [#155](https://github.com/xwp/wp-customize-snapshots/pull/155), [#153](https://github.com/xwp/wp-customize-snapshots/issues/153).
+* Fixed: Prevent changeset session remembrance when browsing in preview iframe. See [#154](https://github.com/xwp/wp-customize-snapshots/pull/154).
+* Added: Include required PHP version (5.3) in readme. See [#160](https://github.com/xwp/wp-customize-snapshots/pull/160), [#159](https://github.com/xwp/wp-customize-snapshots/issues/159).
+* Updated: Dev dependencies.
+
+Props: Sayed Taqui (@sayedwp), Weston Ruter (@westonruter), Miina Sikk (@miina), Derek Herman (@valendesigns), Ryan Kienstra (@kienstra), Anne Louise Currie (@alcurrie).
+
+See [issues and PRs in milestone](https://github.com/xwp/wp-customize-snapshots/milestone/11?closed=1) and [`0.6.2...0.7.0`](https://github.com/xwp/wp-customize-snapshots/compare/0.6.2...0.7.0) commit log.
+
### 0.6.2 - 2017-07-26 ###
* Added: Just like the admin menu has Changesets link under Customize, add Changesets link in admin bar submenu item under Customize. See #143.
* Fixed: Restore frontend changeset preview session resuming, to restore the previously previewed changeset in case of accidentally navigating away from frontend changeset preview. See #145.
diff --git a/readme.txt b/readme.txt
index e75fe574..0a0e0433 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,8 +1,9 @@
=== Customize Snapshots ===
Contributors: xwp, westonruter, valendesigns, utkarshpatel, sayedwp, newscorpau
-Requires at least: 4.6
-Tested up to: 4.8.1
-Stable tag: 0.6.2
+Requires at least: 4.7
+Tested up to: 4.9
+Stable tag: 0.7.0
+Requires PHP: 5.3
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: customizer, customize, changesets
@@ -11,9 +12,9 @@ Provide a UI for managing Customizer changesets; save changesets as named drafts
== Description ==
-Customize Snapshots is the feature plugin which prototyped [Customizer changesets](https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/); this feature was [merged](https://make.wordpress.org/core/2016/10/12/customize-changesets-formerly-transactions-merge-proposal/) as part of WordPress 4.7.
-The term “snapshots” was chosen because the Customizer feature revolved around saving the state (taking a snapshot) of the Customizer at a given time so that the changes could be saved as a draft and scheduled for future publishing.
-While the plugin's technical infrastructure for changesets was merged in WordPress 4.7,the user interface still remains largely in the Customize Snapshots plugin, in which we will continue to iterate and prototype features to merge into core.
+Customize Snapshots is the feature plugin which prototyped [Customizer changesets](https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/); this feature was [merged](https://make.wordpress.org/core/2016/10/12/customize-changesets-formerly-transactions-merge-proposal/) as part of WordPress 4.7. The term “snapshots” was chosen because the Customizer feature revolved around saving the state (taking a snapshot) of the Customizer at a given time so that the changes could be saved as a draft and scheduled for future publishing.
+
+While the plugin's technical infrastructure for changesets was merged in WordPress 4.7, the user interface still remains largely in the Customize Snapshots plugin, in which we will continue to iterate and prototype features to merge into core.
For a rundown of all the features, see the screenshots below as well as the 0.6 release video:
@@ -40,6 +41,20 @@ Requires PHP 5.3+. **Development of this plugin is done [on GitHub](https://gith
== Changelog ==
+= 0.7.0 - 2017-11-15 =
+
+* Added: Add compatibility with 4.9, re-using features of the plugin that have been merged into core in this release. Increase minimum required version of WordPress to 4.7. See [#162](https://github.com/xwp/wp-customize-snapshots/pull/162).
+* Added: Remove hiding of Add New links for changesets in favor of just redirecting `post-new.php` to Customizer. See [#156](https://github.com/xwp/wp-customize-snapshots/pull/156).
+* Added: Allow publishing from preview via link in admin bar. See [#115](https://github.com/xwp/wp-customize-snapshots/pull/115), [#103](https://github.com/xwp/wp-customize-snapshots/issues/103).
+* Updated: Change link text for post list table action from “Edit” to “Inspect”. See [#155](https://github.com/xwp/wp-customize-snapshots/pull/155), [#153](https://github.com/xwp/wp-customize-snapshots/issues/153).
+* Fixed: Prevent changeset session remembrance when browsing in preview iframe. See [#154](https://github.com/xwp/wp-customize-snapshots/pull/154).
+* Added: Include required PHP version (5.3) in readme. See [#160](https://github.com/xwp/wp-customize-snapshots/pull/160), [#159](https://github.com/xwp/wp-customize-snapshots/issues/159).
+* Updated: Dev dependencies.
+
+Props: Sayed Taqui (@sayedwp), Weston Ruter (@westonruter), Miina Sikk (@miina), Derek Herman (@valendesigns), Ryan Kienstra (@kienstra), Anne Louise Currie (@alcurrie).
+
+See [issues and PRs in milestone](https://github.com/xwp/wp-customize-snapshots/milestone/11?closed=1) and [`0.6.2...0.7.0`](https://github.com/xwp/wp-customize-snapshots/compare/0.6.2...0.7.0) commit log.
+
= 0.6.2 - 2017-07-26 =
* Added: Just like the admin menu has Changesets link under Customize, add Changesets link in admin bar submenu item under Customize. See #143.
diff --git a/tests/php/test-class-ajax-customize-snapshot-manager-back-compat.php b/tests/php/test-class-ajax-customize-snapshot-manager-back-compat.php
deleted file mode 100644
index d33c9957..00000000
--- a/tests/php/test-class-ajax-customize-snapshot-manager-back-compat.php
+++ /dev/null
@@ -1,626 +0,0 @@
-compat ) {
- $this->markTestSkipped( 'WordPress Version 4.6.x or below is required for this test-case.' );
- }
-
- remove_all_actions( 'wp_ajax_customize_save' );
- remove_all_actions( 'wp_ajax_customize_update_snapshot' );
- $this->plugin = new Plugin();
- $this->set_input_vars();
- $this->plugin->init();
- if ( $this->plugin->compat ) {
- $this->post_type_slug = Post_Type_Back_Compat::SLUG;
- } else {
- $this->post_type_slug = Post_Type::SLUG;
- }
- }
-
- /**
- * Grant Customize to all.
- *
- * @param array $allcaps All caps.
- * @param array $caps Caps.
- * @param array $args Args.
- * @return array Caps.
- */
- public function filter_grant_customize_to_all( $allcaps, $caps, $args ) {
- if ( ! empty( $args ) && 'customize' === $args[0] ) {
- $allcaps = array_merge( $allcaps, array_fill_keys( $caps, true ) );
- }
- return $allcaps;
- }
-
- /**
- * Set input vars.
- *
- * @param array $vars Input vars.
- * @param string $method Request method.
- */
- public function set_input_vars( array $vars = array(), $method = 'POST' ) {
- $vars = array_merge(
- array(
- 'customized' => wp_json_encode( array( 'anyonecanedit' => 'Hello' ) ),
- 'wp_customize' => 'on',
- 'customize_snapshot_uuid' => self::UUID,
- 'nonce' => wp_create_nonce( 'save-customize_' . get_stylesheet() ),
- ),
- $vars
- );
- $_GET = $_POST = $_REQUEST = wp_slash( $vars );
- $_SERVER['REQUEST_METHOD'] = $method;
- }
-
- /**
- * Set current user.
- *
- * @param string $role Role.
- * @return int User Id.
- */
- function set_current_user( $role ) {
- $user_id = $this->factory()->user->create( array( 'role' => $role ) );
- wp_set_current_user( $user_id );
- $_GET['nonce'] = $_REQUEST['nonce'] = $_POST['nonce'] = wp_create_nonce( 'save-customize_' . get_stylesheet() );
- return $user_id;
- }
-
- /**
- * Add anyonecanedit Customize setting.
- */
- function add_setting() {
- $this->plugin->customize_snapshot_manager->customize_manager->add_setting( 'anyonecanedit', array(
- 'capability' => 'exist',
- ) );
- }
-
- /**
- * Tear down.
- */
- function tearDown() {
- $this->plugin->customize_snapshot_manager->customize_manager = null;
- $this->manager = null;
- $this->actioned_snapshot = null;
- $this->actioned_snapshot_manager = null;
- $this->filtered_customizer = null;
- unset( $GLOBALS['wp_customize'] );
- unset( $GLOBALS['wp_scripts'] );
- unset( $_SERVER['REQUEST_METHOD'] );
- unset( $_REQUEST['wp_customize'] );
- unset( $_REQUEST['customize_snapshot_uuid'] );
- unset( $_REQUEST['preview'] );
- parent::tearDown();
- }
-
- /**
- * Helper to keep it DRY
- *
- * @param string $action Action.
- */
- protected function make_ajax_call( $action ) {
- try {
- $this->_handleAjax( $action );
- } catch ( \WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- }
-
- /**
- * Testing passing Customize save for a user who has customize_publish capability.
- */
- function test_ajax_customize_save_passing_customize_publish() {
- $this->set_current_user( 'administrator' );
- $this->plugin->customize_snapshot_manager->customize_manager->setup_theme();
- $this->add_setting();
-
- $snapshot_uuid = $this->plugin->customize_snapshot_manager->current_snapshot_uuid;
- $snapshot_post_id = $this->plugin->customize_snapshot_manager->post_type->find_post( $snapshot_uuid );
- $this->assertNull( $snapshot_post_id );
-
- // Get the results.
- $this->make_ajax_call( 'customize_save' );
- $response = json_decode( $this->_last_response, true );
-
- $this->assertTrue( $response['success'] );
- if ( method_exists( 'WP_Customize_Manager', 'prepare_setting_validity_for_js' ) ) {
- $this->assertArrayHasKey( 'setting_validities', $response['data'] );
- $this->assertArrayHasKey( 'anyonecanedit', $response['data']['setting_validities'] );
- $this->assertTrue( $response['data']['setting_validities']['anyonecanedit'] );
- }
- $this->assertArrayHasKey( 'new_customize_snapshot_uuid', $response['data'] );
- $this->assertTrue( Customize_Snapshot_Manager::is_valid_uuid( $response['data']['new_customize_snapshot_uuid'] ) );
-
- $snapshot_post_id = $this->plugin->customize_snapshot_manager->post_type->find_post( $snapshot_uuid );
- $this->assertNotNull( $snapshot_post_id );
- $snapshot_post = get_post( $snapshot_post_id );
- $this->assertSame(
- $this->plugin->customize_snapshot_manager->customize_manager->unsanitized_post_values(),
- wp_list_pluck( json_decode( $snapshot_post->post_content, true ), 'value' )
- );
- }
-
- /**
- * Testing failing a user who lacks customize_publish capability.
- */
- function test_ajax_customize_save_failing_customize_publish() {
-
- add_filter( 'user_has_cap', array( $this, 'filter_grant_customize_to_all' ), 10, 4 );
- $this->set_current_user( 'editor' );
- $this->plugin->customize_snapshot_manager->customize_manager->setup_theme();
-
- // Get the results.
- $this->make_ajax_call( 'customize_save' );
- $response = json_decode( $this->_last_response, true );
- $expected_results = array(
- 'success' => false,
- 'data' => array(
- 'error' => 'customize_publish_unauthorized',
- ),
- );
-
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Testing capabilities check for the update_snapshot method.
- */
- function test_ajax_update_snapshot_nonce_check() {
- $this->set_current_user( 'administrator' );
- $this->set_input_vars( array(
- 'action' => Customize_Snapshot_Manager::AJAX_ACTION,
- 'nonce' => 'bad-nonce-12345',
- ) );
-
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
- $expected_results = array(
- 'success' => false,
- 'data' => 'bad_nonce',
- );
-
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Testing REQUEST_METHOD for the update_snapshot method.
- */
- function test_ajax_update_snapshot_post_check() {
- $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 ),
- ),
- 'GET'
- );
- $this->plugin->customize_snapshot_manager->customize_manager->setup_theme();
- $this->add_setting();
-
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
- $expected_results = array(
- 'success' => false,
- 'data' => 'bad_method',
- );
-
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Testing capabilities check for the update_snapshot method
- *
- * @dataProvider data_update_snapshot_cap_check
- *
- * @param string $role The role we're checking caps against.
- * @param array $expected_results Expected results.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Back_Compat::check_customize_publish_authorization()
- */
- function test_ajax_update_snapshot_cap_check( $role, $expected_results ) {
- $this->set_current_user( $role );
- $this->set_input_vars(
- array(
- 'action' => Customize_Snapshot_Manager::AJAX_ACTION,
- 'nonce' => wp_create_nonce( Customize_Snapshot_Manager::AJAX_ACTION ),
- )
- );
- $this->add_setting();
-
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
-
- if ( $response['success'] ) {
- $this->assertNotEmpty( $response['data']['edit_link'] );
- $this->assertNotEmpty( $response['data']['snapshot_publish_date'] );
- $this->assertNotEmpty( $response['data']['title'] );
- unset( $response['data']['edit_link'] );
- unset( $response['data']['snapshot_publish_date'] );
- unset( $response['data']['title'] );
- }
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Data provider for test_ajax_update_snapshot_cap_check().
- *
- * Provides various post_args to induce error messages that can be
- * compared to the expected_results.
- *
- * @return array {
- * @type array {
- * @string string $role The role that will test caps for.
- * @array array $expected_results The expected results from the ajax call.
- * }
- * }
- */
- function data_update_snapshot_cap_check() {
- $data = array(
- array(
- 'subscriber',
- array(
- 'success' => false,
- 'data' => 'customize_not_allowed',
- ),
- ),
- array(
- 'contributor',
- array(
- 'success' => false,
- 'data' => 'customize_not_allowed',
- ),
- ),
- array(
- 'author',
- array(
- 'success' => false,
- 'data' => 'customize_not_allowed',
- ),
- ),
- array(
- 'editor',
- array(
- 'success' => false,
- 'data' => 'customize_not_allowed',
- ),
- ),
- );
-
- $success_data = array(
- 'administrator',
- array(
- 'success' => true,
- 'data' => array(
- 'errors' => null,
- 'setting_validities' => array(
- 'anyonecanedit' => true,
- ),
- ),
- ),
- );
-
- require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
- if ( ! method_exists( 'WP_Customize_Manager', 'prepare_setting_validity_for_js' ) ) {
- $success_data[1]['data'] = array( 'errors' => null );
- }
- $data[] = $success_data;
-
- return $data;
- }
-
- /**
- * Testing post_data for the update_snapshot method
- */
- function test_ajax_update_snapshot_post_data_check() {
- unset( $GLOBALS['wp_customize'] );
- remove_all_actions( 'wp_ajax_' . Customize_Snapshot_Manager::AJAX_ACTION );
-
- $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' => null,
- ) );
-
- $this->plugin = new Plugin();
- $this->plugin->init();
- $this->add_setting();
-
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
- $expected_results = array(
- 'success' => false,
- 'data' => 'missing_snapshot_customized',
- );
-
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Testing a successful response for the update_snapshot method
- */
- function test_ajax_update_snapshot_success() {
- $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,
- ) );
- $this->add_setting();
-
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
- $this->assertNull( $response['data']['errors'] );
- }
-
- /**
- * Helper function to make the Ajax call directy to `Customize_Snapshot_Manager::save_snapshot`.
- *
- * @see Customize_Snapshot_Manager::save_snapshot()
- */
- function make_save_snapshot_ajax_call() {
- try {
- ini_set( 'implicit_flush', false );
- ob_start();
- $manager = new Customize_Snapshot_Manager( $this->plugin );
- $manager->publish_snapshot_with_customize_save_after();
- $buffer = ob_get_clean();
- if ( ! empty( $buffer ) ) {
- $this->_last_response = $buffer;
- }
- } catch ( \WPAjaxDieContinueException $e ) {
- 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 );
-
- $post_type_obj = get_post_type_object( $this->post_type_slug );
- $setting_key = 'anyonecanedit';
- $tomorrow = date( 'Y-m-d H:i:s', time() + 86400 );
- $this->set_current_user( 'administrator' );
- $this->assertTrue( current_user_can( $post_type_obj->cap->publish_posts ) );
- $title = 'Hello World! \o/';
- $this->set_input_vars( array(
- 'action' => Customize_Snapshot_Manager::AJAX_ACTION,
- 'title' => $title,
- 'nonce' => wp_create_nonce( Customize_Snapshot_Manager::AJAX_ACTION ),
- 'customize_snapshot_uuid' => self::UUID,
- 'customized' => wp_json_encode( array( $setting_key => 'Hello' ) ),
- 'status' => 'future',
- '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,
- 'title' => $title,
- ),
- );
- 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 ) );
- $this->assertEquals( $title, get_the_title( $post_id ) );
- }
-
- /**
- * Test updating a snapshot when the user does not have the customize_publish capability.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::handle_update_snapshot_request()
- */
- function test_ajax_update_snapshot_ok_for_draft_and_pending_but_not_future() {
- unset( $GLOBALS['wp_customize'] );
- remove_all_actions( 'wp_ajax_' . Customize_Snapshot_Manager::AJAX_ACTION );
-
- $post_type_obj = get_post_type_object( $this->post_type_slug );
- $setting_key = 'anyonecanedit';
- add_filter( 'user_has_cap', function( $allcaps, $caps, $args ) {
- $allcaps['customize'] = true;
- if ( ! empty( $allcaps['edit_posts'] ) && ! empty( $args ) && 'customize' === $args[0] ) {
- $allcaps = array_merge( $allcaps, array_fill_keys( $caps, true ) );
- }
- return $allcaps;
- }, 10, 3 );
- $tomorrow = date( 'Y-m-d H:i:s', time() + 86400 );
- $this->set_current_user( 'contributor' );
- $this->assertFalse( current_user_can( $post_type_obj->cap->publish_posts ) );
- $post_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' ) ),
- 'publish_date' => $tomorrow, // Tomorrow.
- );
-
- $this->plugin = new Plugin();
- $this->plugin->init();
- $this->add_setting();
-
- // Draft pass.
- $post_vars['status'] = 'draft';
- $this->set_input_vars( $post_vars );
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
- $response = json_decode( $this->_last_response, true );
- $this->_last_response = '';
- $this->assertTrue( $response['success'] );
-
- // Pending pass.
- $post_vars['status'] = 'pending';
- $this->set_input_vars( $post_vars );
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
- $response = json_decode( $this->_last_response, true );
- $this->_last_response = '';
- $this->assertTrue( $response['success'] );
-
- // Future fail.
- $post_vars['status'] = 'future';
- $this->set_input_vars( $post_vars );
- $this->make_ajax_call( Customize_Snapshot_Manager::AJAX_ACTION );
- $response = json_decode( $this->_last_response, true );
- $expected_results = array(
- 'success' => false,
- 'data' => 'customize_not_allowed',
- );
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Test actions and filters to make sure they are passing correct params.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::handle_update_snapshot_request()
- */
- function test_handle_update_snapshot_request_actions_and_filters() {
- unset( $GLOBALS['wp_customize'] );
- remove_all_actions( 'wp_ajax_' . Customize_Snapshot_Manager::AJAX_ACTION );
-
- add_filter( 'user_has_cap', function( $allcaps, $caps, $args ) {
- $allcaps['customize'] = true;
- if ( ! empty( $allcaps['edit_posts'] ) && ! empty( $args ) && 'customize' === $args[0] ) {
- $allcaps = array_merge( $allcaps, array_fill_keys( $caps, true ) );
- }
- return $allcaps;
- }, 10, 3 );
- $this->set_current_user( 'contributor' );
- $post_vars = array(
- 'action' => Customize_Snapshot_Manager::AJAX_ACTION,
- 'nonce' => wp_create_nonce( Customize_Snapshot_Manager::AJAX_ACTION ),
- 'customize_snapshot_uuid' => self::UUID,
- );
-
- $this->plugin = new Plugin();
- $this->plugin->init();
- $this->add_setting();
-
- $that = $this; // For PHP 5.3.
- add_action( 'customize_snapshot_save_before', function( $test_snapshot, $test_snapshot_manager ) use ( $that ) {
- $that->actioned_snapshot = $test_snapshot;
- $that->actioned_snapshot_manager = $test_snapshot_manager;
- }, 10, 2 );
- add_filter( 'customize_save_response', function( $data, $test_customizer ) use ( $that ) {
- $that->filtered_customizer = $test_customizer;
- return $data;
- }, 10, 2 );
-
- $this->set_input_vars( $post_vars );
- $this->make_ajax_call( Customize_Snapshot_Manager_Back_Compat::AJAX_ACTION );
-
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->ensure_customize_manager();
- $manager->init();
-
- $this->assertEquals( $manager->snapshot(), $this->actioned_snapshot );
- $this->assertEquals( $manager, $this->actioned_snapshot_manager );
- $this->assertEquals( $manager->customize_manager, $this->filtered_customizer );
- }
-}
diff --git a/tests/php/test-class-customize-snapshot-back-compat.php b/tests/php/test-class-customize-snapshot-back-compat.php
deleted file mode 100644
index e0da98ce..00000000
--- a/tests/php/test-class-customize-snapshot-back-compat.php
+++ /dev/null
@@ -1,363 +0,0 @@
-plugin = get_plugin_instance();
- if ( ! $this->plugin->compat ) {
- $this->markTestSkipped( 'WordPress Version 4.6.x or below is required for this test-case.' );
- }
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $GLOBALS['wp_customize'] = new \WP_Customize_Manager(); // WPCS: override ok.
- $this->snapshot_manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->wp_customize = $GLOBALS['wp_customize'];
- wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
- $this->wp_customize->add_setting( 'foo', array( 'default' => 'foo_default' ) );
- $this->wp_customize->add_setting( 'bar', array( 'default' => 'bar_default' ) );
- $this->foo = $this->wp_customize->get_setting( 'foo' );
- $this->bar = $this->wp_customize->get_setting( 'bar' );
- }
-
- /**
- * Bootstrap the customizer.
- */
- public static function setUpBeforeClass() {
- $args = array(
- 'labels' => array(
- 'name' => __( 'Customize Snapshots', 'customize-snapshots' ),
- 'singular_name' => __( 'Customize Snapshot', 'customize-snapshots' ),
- ),
- 'public' => false,
- 'capability_type' => 'post',
- 'map_meta_cap' => true,
- 'hierarchical' => false,
- 'rewrite' => false,
- 'delete_with_user' => false,
- 'supports' => array( 'title', 'author', 'revisions' ),
- );
- register_post_type( self::POST_TYPE, $args );
- }
-
- /**
- * Tear down after class.
- */
- public static function tearDownAfterClass() {
- _unregister_post_type( self::POST_TYPE );
- }
-
- /**
- * Tear down.
- */
- function tearDown() {
- $this->wp_customize = null;
- unset( $GLOBALS['wp_customize'] );
- unset( $GLOBALS['wp_scripts'] );
- $this->filtered_snapshot = null;
- parent::tearDown();
- }
-
- /**
- * Test constructor.
- *
- * @see Customize_Snapshot::__construct()
- */
- function test_construct() {
- $manager = $this->snapshot_manager;
- $manager->init();
- $data = array( 'foo' => array( 'value' => 'bar' ) );
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => $data,
- ) );
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
- $this->assertEquals( $data, $snapshot->data() );
- }
-
- /**
- * Test UUID.
- *
- * @see Customize_Snapshot::uuid()
- */
- function test_uuid() {
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertEquals( self::UUID, $manager->snapshot()->uuid() );
- }
-
- /**
- * Test bad UUID.
- *
- * @see Customize_Snapshot::uuid()
- */
- function test_uuid_throws_exception() {
- try {
- new Customize_Snapshot_Back_Compat( $this->snapshot_manager, '1234-invalid-UUID' );
- } catch ( \Exception $e ) {
- $this->assertContains( 'You\'ve entered an invalid snapshot UUID.', $e->getMessage() );
- return;
- }
- $this->fail( 'An expected exception has not been raised.' );
- }
-
- /**
- * Test data.
- *
- * @see Customize_Snapshot::data()
- */
- function test_data() {
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- $manager->snapshot()->set( array( 'foo' => array( 'value' => 'foo_default' ) ) );
- $this->assertNotEmpty( $manager->snapshot()->data() );
- $manager->snapshot()->set( array( 'foo' => array( 'value' => 'foo_custom' ) ) );
- $expected = array(
- 'foo' => array(
- 'value' => 'foo_custom',
- ),
- );
- $this->assertEquals( $expected, $manager->snapshot()->data() );
- }
-
- /**
- * Test snapshot settings.
- *
- * @see Customize_Snapshot::settings()
- */
- function test_settings() {
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- $this->assertEmpty( $manager->snapshot()->settings() );
- $manager->snapshot()->set( array( 'foo' => array( 'value' => 'foo_default' ) ) );
- $this->assertNotEmpty( $manager->snapshot()->settings() );
- }
-
- /**
- * Test status.
- *
- * @see Customize_Snapshot::settings()
- */
- function test_status() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
- $this->assertNull( $snapshot->status() );
-
- $data = array( 'foo' => array( 'value' => 'bar' ) );
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => $data,
- 'status' => 'draft',
- ) );
-
- $this->assertEquals( 'draft', $snapshot->status() );
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'status' => 'publish',
- ) );
- $this->assertEquals( 'publish', $snapshot->status() );
- }
-
- /**
- * Test set.
- *
- * @see Customize_Snapshot::set()
- */
- function test_set() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- $this->bar->capability = 'do_not_allow';
- add_filter( 'customize_sanitize_foo', 'strtoupper' );
-
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
- $result = $snapshot->set( array(
- 'foo' => array( 'value' => 'ok' ),
- 'bar' => array( 'value' => 'unauthorized' ),
- 'baz' => array( 'value' => 'unrecognized' ),
- ) );
-
- $this->assertArrayHasKey( 'errors', $result );
- $this->assertInstanceOf( 'WP_Error', $result['errors'] );
- $wp_error = $result['errors'];
- $this->assertArrayHasKey( 'unauthorized_settings', $wp_error->errors );
- $this->assertArrayHasKey( 'unrecognized_settings', $wp_error->errors );
-
- $this->assertArrayHasKey( 'sanitized', $result );
- $this->assertArrayHasKey( 'foo', $result['sanitized'] );
- $this->assertArrayNotHasKey( 'bar', $result['sanitized'] );
- $this->assertArrayNotHasKey( 'baz', $result['sanitized'] );
- $this->assertEquals( 'OK', $result['sanitized']['foo'] );
-
- $this->assertArrayHasKey( 'validities', $result );
- $this->assertArrayHasKey( 'foo', $result['validities'] );
- $this->assertTrue( $result['validities']['foo'] );
-
- $this->assertEmpty( $snapshot->data() );
-
- // Success with populated value.
- $result = $snapshot->set( array( 'foo' => array( 'value' => 'ok' ) ) );
- $this->assertNull( $result['errors'] );
- $resultant_data = $snapshot->data();
- $this->assertEquals( 'ok', $resultant_data['foo']['value'] );
- }
-
- /**
- * Test set with varying setting params.
- *
- * @see Customize_Snapshot::set()
- */
- function test_set_with_varying_setting_params() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
-
- $result = $snapshot->set( array( 'foo' => array( 'value' => 'ok' ) ) );
- $this->assertNull( $result['errors'] );
- $resultant_data = $snapshot->data();
- $this->assertEquals( 'ok', $resultant_data['foo']['value'] );
-
- // Check setting a param without a value, ensuring that foo still remains but snapshot is amended.
- $result = $snapshot->set( array( 'bar' => array( 'extra' => 'ok' ) ) );
- $this->assertNull( $result['errors'] );
- $resultant_data = $snapshot->data();
- $this->assertEquals( 'ok', $resultant_data['foo']['value'] );
- $this->assertArrayHasKey( 'extra', $resultant_data['bar'] );
- $this->assertNull( $resultant_data['bar']['value'] );
- }
-
- /**
- * Test set with a non-array param.
- *
- * @see Customize_Snapshot::set()
- * @expectedException Exception
- */
- function test_set_with_non_array_params() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->ensure_customize_manager();
- $manager->init();
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
- $snapshot->set( array( 'foo' => 'bad' ) );
- }
-
- /**
- * Test saved.
- *
- * @see Customize_Snapshot::saved()
- */
- function test_saved() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
- $this->assertFalse( $snapshot->saved() );
-
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => array( 'foo' => array( 'value' => 'bar' ) ),
- ) );
- }
-
- /**
- * Snapshot object passed in customize_snapshot_save filter.
- *
- * @var Customize_Snapshot
- */
- public $filtered_snapshot;
-
- /**
- * Test that the snapshot object is passed as the second filter param.
- *
- * @see Customize_Snapshot::save()
- */
- function test_filter_customize_snapshot_save() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->ensure_customize_manager();
- $manager->init();
-
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
-
- $that = $this; // For PHP 5.3.
- add_filter( 'customize_snapshot_save', function( $data, $test_snapshot ) use ( $that ) {
- $that->filtered_snapshot = $test_snapshot;
- return $data;
- }, 10, 2 );
-
- $snapshot->save( array(
- 'uuid' => self::UUID,
- 'data' => array( 'foo' => array( 'value' => 'bar' ) ),
- ) );
-
- $this->assertEquals( $snapshot, $this->filtered_snapshot );
- }
-}
diff --git a/tests/php/test-class-customize-snapshot-manager-back-compat.php b/tests/php/test-class-customize-snapshot-manager-back-compat.php
deleted file mode 100644
index 6592c6a7..00000000
--- a/tests/php/test-class-customize-snapshot-manager-back-compat.php
+++ /dev/null
@@ -1,746 +0,0 @@
-plugin = get_plugin_instance();
- if ( ! $this->plugin->compat ) {
- $this->markTestSkipped( 'WordPress Version 4.6.x or below is required for this test-case.' );
- }
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $GLOBALS['wp_customize'] = new \WP_Customize_Manager(); // WPCS: global override ok.
- $this->wp_customize = $GLOBALS['wp_customize'];
-
- $this->wp_customize->add_setting( 'foo', array( 'default' => 'foo_default' ) );
- $this->wp_customize->add_setting( 'bar', array( 'default' => 'bar_default' ) );
-
- $this->manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->manager->init();
- $this->user_id = $this->factory()->user->create( array( 'role' => 'administrator' ) );
-
- remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
- remove_action( 'after_setup_theme', 'twentysixteen_setup' );
- remove_all_actions( 'send_headers' ); // Prevent X-hacker header in VIP Quickstart.
-
- // For why these hooks have to be removed, see .
- $this->css_concat_init_priority = has_action( 'init', 'css_concat_init' );
- if ( $this->css_concat_init_priority ) {
- remove_action( 'init', 'css_concat_init', $this->css_concat_init_priority );
- }
- $this->js_concat_init_priority = has_action( 'init', 'js_concat_init' );
- if ( $this->js_concat_init_priority ) {
- remove_action( 'init', 'js_concat_init', $this->js_concat_init_priority );
- }
- }
-
- /**
- * Clean up global scope.
- */
- function clean_up_global_scope() {
- unset( $GLOBALS['wp_scripts'] );
- unset( $GLOBALS['wp_styles'] );
- unset( $_REQUEST['customize_snapshot_uuid'] );
- unset( $_REQUEST['wp_customize_preview_ajax'] );
- parent::clean_up_global_scope();
- }
-
- /**
- * Tear down.
- */
- function tearDown() {
- $this->wp_customize = null;
- $this->manager = null;
- unset( $GLOBALS['wp_customize'] );
- unset( $GLOBALS['screen'] );
- $_REQUEST = array();
- parent::tearDown();
- }
-
- /**
- * Set wp_customize query param.
- */
- function do_customize_on() {
- $_REQUEST['wp_customize'] = 'on';
- }
-
- /**
- * Do Customize boot actions.
- *
- * @param bool $on Whether to turn on Customizer.
- */
- function do_customize_boot_actions( $on = false ) {
- $_SERVER['REQUEST_METHOD'] = 'POST';
- do_action( 'setup_theme' );
- $_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
- do_action( 'after_setup_theme' );
- do_action( 'init' );
- do_action( 'wp_loaded' );
- do_action( 'wp', $GLOBALS['wp'] );
- if ( $on ) {
- $this->do_customize_on();
- }
- }
-
- /**
- * Tests load_snapshot.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::init()
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::load_snapshot()
- */
- public function test_load_snapshot() {
- global $wp_actions;
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $this->plugin->customize_snapshot_manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => array(
- 'blogname' => array( 'value' => 'Hello' ),
- ),
- 'status' => 'draft',
- ) );
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- unset( $wp_actions['setup_theme'] );
- unset( $wp_actions['wp_loaded'] );
- $manager->init();
- $this->assertNotEmpty( $manager->customize_manager );
- $this->assertNotEmpty( $manager->snapshot );
-
- $this->assertEquals( 10, has_action( 'setup_theme', array( $manager, 'import_snapshot_data' ) ) );
- $this->assertEquals( 10, has_action( 'wp_head', 'wp_no_robots' ) );
- $this->assertEquals( 11, has_action( 'wp_loaded', array( $manager, 'preview_snapshot_settings' ) ) );
- }
-
- /**
- * Test constructor with Customizer.
- *
- * @see Customize_Snapshot_Manager_Back_Compat::__construct()
- */
- function test_construct_with_customize() {
- wp_set_current_user( $this->user_id );
- $this->do_customize_boot_actions( true );
- $this->assertTrue( is_customize_preview() );
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertEquals( $manager->current_snapshot_uuid, self::UUID );
- $this->assertInstanceOf( 'CustomizeSnapshots\Post_Type_Back_Compat', $manager->post_type );
- $this->assertInstanceOf( 'CustomizeSnapshots\Customize_Snapshot_Back_Compat', $manager->snapshot() );
- $this->assertEquals( 0, has_action( 'init', array( $manager, 'create_post_type' ) ) );
- $this->assertEquals( 10, has_action( 'customize_controls_enqueue_scripts', array( $manager, 'enqueue_controls_scripts' ) ) );
- }
-
- /**
- * Test init.
- *
- * @see Customize_Snapshot_Manager_Back_Compat::init()
- */
- function test_init() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertEquals( 10, has_filter( 'customize_refresh_nonces', array( $manager, 'filter_customize_refresh_nonces' ) ) );
- $this->assertEquals( 10, has_action( 'template_redirect', array( $manager, 'show_theme_switch_error' ) ) );
- $this->assertEquals( 10, has_action( 'customize_save_after', array( $manager, 'publish_snapshot_with_customize_save_after' ) ) );
- $this->assertEquals( 10, has_action( 'transition_post_status', array( $manager, 'save_settings_with_publish_snapshot' ) ) );
- $this->assertEquals( 10, has_action( 'wp_ajax_customize_update_snapshot', array( $manager, 'handle_update_snapshot_request' ) ) );
- $this->assertEquals( 10, has_action( 'customize_preview_init', array( $manager, 'customize_preview_init' ) ) );
- $this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $manager, 'enqueue_frontend_scripts' ) ) );
- $this->assertEquals( 10, has_action( 'customize_save', array( $manager, 'check_customize_publish_authorization' ) ) );
- }
-
- /*
- * For Customize_Snapshot_Manager_Back_Compat::Customize_Snapshot_Manager_Back_Compat(), see Test_Ajax_Customize_Snapshot_Manager_Back_Compat::test_ajax_update_snapshot_cap_check().
- */
-
- /**
- * Test customize preview init.
- *
- * @see Customize_Snapshot_Manager::customize_preview_init()
- */
- function test_customize_preview_init() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $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_Back_Compat( $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.
- *
- * @see Customize_Snapshot_Manager::enqueue_frontend_scripts()
- */
- function test_enqueue_frontend_scripts() {
- $this->plugin->register_scripts( wp_scripts() );
- $this->plugin->register_styles( wp_styles() );
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertFalse( wp_script_is( 'customize-snapshots-frontend', 'enqueued' ) );
- $manager->enqueue_frontend_scripts();
- $this->assertFalse( wp_script_is( 'customize-snapshots-frontend', 'enqueued' ) );
-
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertFalse( wp_script_is( 'customize-snapshots-frontend', 'enqueued' ) );
- $manager->enqueue_frontend_scripts();
- $this->assertTrue( wp_script_is( 'customize-snapshots-frontend', 'enqueued' ) );
- }
-
- /**
- * Test filter_customize_refresh_nonces.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Back_Compat::filter_customize_refresh_nonces()
- */
- function test_filter_customize_refresh_nonces() {
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->assertArrayHasKey( 'snapshot', $manager->filter_customize_refresh_nonces( array() ) );
- }
-
- /**
- * Tests show_theme_switch_error.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Back_Compat::show_theme_switch_error()
- */
- function test_show_theme_switch_error() {
- $this->markTestIncomplete();
- }
-
- /**
- * Test publish snapshot with customize_save_after.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Back_Compat::publish_snapshot_with_customize_save_after()
- */
- function test_publish_snapshot_with_customize_save_after() {
- wp_set_current_user( $this->user_id );
- $this->do_customize_boot_actions( true );
- $_POST = array(
- 'nonce' => wp_create_nonce( 'save-customize_' . $this->wp_customize->get_stylesheet() ),
- 'customize_snapshot_uuid' => self::UUID,
- 'customized' => '{"foo":"foo_default","bar":"bar_default"}',
- );
- $_REQUEST['action'] = 'customize_save';
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $this->assertEmpty( $manager->snapshot()->post() );
- $manager->publish_snapshot_with_customize_save_after();
- $this->assertNotEmpty( $manager->snapshot()->post() );
-
- $this->markTestIncomplete( 'Need to test when snapshot->save() returns errors, and when snapshot post save fails.' );
- }
-
- /**
- * Test save_settings_with_publish_snapshot.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Back_Compat::save_settings_with_publish_snapshot()
- */
- public function test_save_settings_with_publish_snapshot() {
- $post_type = $this->manager->post_type;
- $data = array(
- 'blogdescription' => array( 'value' => 'Snapshot blog' ),
- 'unknown_setting_foo' => array( 'value' => 'bar' ),
- 'null_value_baz' => array( 'value' => null ),
- 'foo' => array( 'value' => 'foo' ),
- );
- $validate_data = array(
- 'blogdescription' => array( 'value' => 'Snapshot blog' ),
- 'unknown_setting_foo' => array(
- 'value' => 'bar',
- 'publish_error' => 'unrecognized_setting',
- ),
- 'null_value_baz' => array(
- 'value' => null,
- 'publish_error' => 'null_value',
- ),
- 'foo' => array(
- 'value' => 'foo',
- ),
- );
-
- if ( method_exists( 'WP_Customize_Setting', 'validate' ) ) {
- $validate_data['foo']['publish_error'] = 'you_shell_not_pass';
- add_filter( 'customize_validate_foo', function( $validity ) {
- $validity->add( 'you_shell_not_pass', 'Testing invalid setting while publishing snapshot' );
- return $validity;
- }, 10, 1 );
- }
-
- $post_id = $post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => $data,
- 'status' => 'draft',
- ) );
-
- // Test invalid settings.
- $post = get_post( $post_id );
- $this->manager->save_settings_with_publish_snapshot( 'publish', 'draft', $post );
- $post = get_post( $post_id );
- $this->assertEquals( $validate_data, json_decode( wp_unslash( $post->post_content ), true ) );
- $this->assertEquals( 'pending', $post->post_status );
-
- // Test valid settings.
- unset( $data['unknown_setting_foo'], $data['null_value_baz'], $data['foo'] );
- $post_id = $post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => $data,
- 'status' => 'publish',
- ) );
- $this->assertEquals( 'publish', get_post_status( $post_id ) );
- $this->assertEquals( 'Snapshot blog', get_bloginfo( 'description' ) );
- }
-
- /*
- * For Customize_Snapshot_Manager::handle_update_snapshot_request(), see Test_Ajax_Customize_Snapshot_Manager_Back_Compat.
- */
-
- /**
- * Tests ensure_customize_manager.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::ensure_customize_manager()
- */
- public function test_ensure_customize_manager() {
- global $wp_customize;
- $wp_customize = null; // WPCS: global override ok.
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->assertEmpty( $manager->customize_manager );
- $manager->ensure_customize_manager();
- $this->assertInstanceOf( 'WP_Customize_Manager', $manager->customize_manager );
- $this->assertInstanceOf( 'WP_Customize_Manager', $wp_customize );
- }
-
- /**
- * Test enqueue controls scripts.
- *
- * @see Customize_Snapshot_Manager::enqueue_controls_scripts()
- */
- function test_enqueue_controls_scripts() {
- $this->plugin->register_scripts( wp_scripts() );
- $this->plugin->register_styles( wp_styles() );
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $manager->enqueue_controls_scripts();
- $this->assertTrue( wp_script_is( 'customize-snapshots-compat', 'enqueued' ) );
- $this->assertTrue( wp_style_is( 'customize-snapshots', 'enqueued' ) );
- }
-
- /**
- * Tests import_snapshot_data.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::import_snapshot_data()
- */
- public function test_import_snapshot_data() {
- 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_Back_Compat( $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 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;
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = $this->plugin->customize_snapshot_manager;
- $post_id = $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => array( 'blogname' => array( 'value' => 'Foo' ) ),
- ) );
- $snapshot = new Customize_Snapshot_Back_Compat( $manager, self::UUID );
-
- // Not if admin.
- set_current_screen( 'posts' );
- $pagenow = 'posts.php'; // WPCS: global override ok.
- $this->assertTrue( is_admin() );
- $this->assertFalse( $manager->should_import_and_preview_snapshot( $snapshot ) );
-
- // Not if theme switch error.
- set_current_screen( 'customize' );
- $pagenow = 'customize.php'; // WPCS: global override ok.
- update_post_meta( $post_id, '_snapshot_theme', 'Foo' );
- $this->assertFalse( $manager->should_import_and_preview_snapshot( $snapshot ) );
- delete_post_meta( $post_id, '_snapshot_theme' );
-
- // Not if customize_save.
- $_REQUEST['action'] = 'customize_save';
- $this->assertFalse( $manager->should_import_and_preview_snapshot( $snapshot ) );
- unset( $_REQUEST['action'] );
-
- // Not if published snapshot.
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'status' => 'publish',
- ) );
- $this->assertFalse( $manager->should_import_and_preview_snapshot( $snapshot ) );
- $manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'status' => 'draft',
- ) );
-
- // Not if unsanitized post values is not empty.
- $manager->customize_manager = new \WP_Customize_Manager();
- $wp_customize = $manager->customize_manager; // WPCS: global override ok.
- $wp_customize->set_post_value( 'name', 'value' );
- $this->assertNotEmpty( $manager->customize_manager->unsanitized_post_values() );
- $this->assertFalse( $manager->should_import_and_preview_snapshot( $snapshot ) );
-
- // OK.
- $manager->customize_manager = new \WP_Customize_Manager();
- $wp_customize = $manager->customize_manager; // WPCS: global override ok.
- $this->assertTrue( $manager->should_import_and_preview_snapshot( $snapshot ) );
- }
-
- /**
- * Tests get_theme_switch_error.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::get_theme_switch_error()
- */
- function test_get_theme_switch_error() {
- $this->markTestIncomplete();
- }
-
- /**
- * Tests is_previewing_settings.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::is_previewing_settings()
- */
- public function test_is_previewing_settings() {
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $this->plugin->customize_snapshot_manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'data' => array( 'blogname' => array( 'value' => 'Foo' ) ),
- ) );
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
- $manager->preview_snapshot_settings();
- $this->assertTrue( $manager->is_previewing_settings() );
- }
-
- /**
- * Tests 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_Back_Compat( $this->plugin );
- $this->assertFalse( $manager->is_previewing_settings() );
- do_action( 'customize_preview_init' );
- $this->assertTrue( $manager->is_previewing_settings() );
- }
-
- /**
- * Tests preview_snapshot_settings.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::preview_snapshot_settings()
- */
- public function test_preview_snapshot_settings() {
- 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_Back_Compat( $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 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();
- }
-
- /**
- * Tests 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();
- }
-
- /**
- * Tests 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() {
- 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_Back_Compat( $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 ) );
- }
-
- /**
- * Tests 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 );
- $_REQUEST['wp_customize_preview_ajax'] = 'true';
- $_POST['customized'] = wp_slash( wp_json_encode( array( 'blogname' => 'Foo' ) ) );
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->do_customize_boot_actions( true );
- $this->assertTrue( is_customize_preview() );
- $manager->init();
- $this->assertEquals( 12, has_action( 'wp_loaded', array( $manager, 'setup_preview_ajax_requests' ) ) );
- do_action( 'wp_loaded' );
-
- $this->assertFalse( has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
- $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_Back_Compat( $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 \CustomizeSnapshots\Customize_Snapshot_Manager::override_request_method()
- */
- public function test_override_request_method() {
- global $wp;
-
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $this->assertFalse( $manager->override_request_method() );
-
- $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'GET';
- $wp->query_vars['rest_route'] = '/wp/v1/foo';
- $this->assertFalse( $manager->override_request_method() );
- unset( $wp->query_vars['rest_route'] );
-
- $_SERVER['REQUEST_METHOD'] = 'GET';
- $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'GET';
- $this->assertFalse( $manager->override_request_method() );
-
- $_SERVER['REQUEST_METHOD'] = 'GET';
- $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'BAD';
- $this->assertFalse( $manager->override_request_method() );
-
- $_GET = wp_slash( array( 'foo' => '1' ) );
- $_POST = wp_slash( array( 'bar' => '2' ) );
- $_SERVER['REQUEST_METHOD'] = 'POST';
- $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'GET';
- $this->assertTrue( $manager->override_request_method() );
- $this->assertEquals( 'GET', $_SERVER['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() );
- }
-
- /**
- * Test customize menu.
- *
- * @see Customize_Snapshot_Manager::customize_menu()
- */
- public function test_customize_menu() {
- set_current_screen( 'front' );
- $preview_url = home_url( '/' );
-
- $_REQUEST['customize_snapshot_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager_Back_Compat( $this->plugin );
- $manager->init();
-
- require_once( ABSPATH . WPINC . '/class-wp-admin-bar.php' );
- $wp_admin_bar = new \WP_Admin_Bar(); // WPCS: Override OK.
- $this->assertInstanceOf( 'WP_Admin_Bar', $wp_admin_bar );
-
- wp_set_current_user( $this->user_id );
- $this->go_to( home_url( '?customize_snapshot_uuid=' . self::UUID ) );
- $wp_admin_bar->initialize();
- $wp_admin_bar->add_menus();
-
- do_action_ref_array( 'admin_bar_menu', array( &$wp_admin_bar ) );
- $parsed_url = wp_parse_url( $wp_admin_bar->get_node( 'customize' )->href );
- $query_params = array();
- wp_parse_str( $parsed_url['query'], $query_params );
- $this->assertEquals( $preview_url, $query_params['url'] );
- $this->assertEquals( self::UUID, $query_params['customize_snapshot_uuid'] );
- }
-
-}
diff --git a/tests/php/test-class-customize-snapshot-manager-compat.php b/tests/php/test-class-customize-snapshot-manager-compat.php
new file mode 100644
index 00000000..77e97a9b
--- /dev/null
+++ b/tests/php/test-class-customize-snapshot-manager-compat.php
@@ -0,0 +1,259 @@
+plugin = get_plugin_instance();
+ $this->front_param = 'customize_changeset_uuid';
+ require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
+ $GLOBALS['wp_customize'] = new \WP_Customize_Manager( array(
+ 'changeset_uuid' => self::UUID,
+ ) ); // WPCS: global override ok.
+ $this->wp_customize = $GLOBALS['wp_customize'];
+
+ $this->wp_customize->add_setting( 'foo', array( 'default' => 'foo_default' ) );
+ $this->wp_customize->add_setting( 'bar', array( 'default' => 'bar_default' ) );
+
+ $this->manager = $this->get_snapshot_manager_instance( $this->plugin );
+ $this->manager->init();
+ $this->user_id = $this->factory()->user->create( array( 'role' => 'administrator' ) );
+
+ remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
+ remove_action( 'after_setup_theme', 'twentysixteen_setup' );
+ remove_all_actions( 'send_headers' ); // Prevent X-hacker header in VIP Quickstart.
+
+ // For why these hooks have to be removed, see .
+ $this->css_concat_init_priority = has_action( 'init', 'css_concat_init' );
+ if ( $this->css_concat_init_priority ) {
+ remove_action( 'init', 'css_concat_init', $this->css_concat_init_priority );
+ }
+ $this->js_concat_init_priority = has_action( 'init', 'js_concat_init' );
+ if ( $this->js_concat_init_priority ) {
+ remove_action( 'init', 'js_concat_init', $this->js_concat_init_priority );
+ }
+ }
+
+ /**
+ * Clean up global scope.
+ */
+ function clean_up_global_scope() {
+ unset( $GLOBALS['wp_scripts'] );
+ unset( $GLOBALS['wp_styles'] );
+ unset( $_REQUEST[ $this->front_param ] );
+ unset( $_REQUEST['wp_customize_preview_ajax'] );
+ parent::clean_up_global_scope();
+ }
+
+ /**
+ * Tear down.
+ */
+ function tearDown() {
+ $this->wp_customize = null;
+ $this->manager = null;
+ unset( $GLOBALS['wp_customize'] );
+ unset( $GLOBALS['screen'] );
+ $_REQUEST = array();
+ parent::tearDown();
+ }
+
+ /**
+ * Set wp_customize query param.
+ */
+ function do_customize_on() {
+ $_REQUEST['wp_customize'] = 'on';
+ }
+
+ /**
+ * Do Customize boot actions.
+ *
+ * @param bool $on Whether to turn on Customizer.
+ */
+ function do_customize_boot_actions( $on = false ) {
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ do_action( 'setup_theme' );
+ $_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
+ do_action( 'after_setup_theme' );
+ do_action( 'init' );
+ do_action( 'wp_loaded' );
+ do_action( 'wp', $GLOBALS['wp'] );
+ if ( $on ) {
+ $this->do_customize_on();
+ }
+ }
+
+ /**
+ * Get snapshot manager instance according to WP version.
+ *
+ * @param Plugin $plugin Plugin object.
+ *
+ * @return Customize_Snapshot_Manager_Compat Manager new instance.
+ */
+ function get_snapshot_manager_instance( $plugin ) {
+ return new Customize_Snapshot_Manager_Compat( $plugin );
+ }
+
+ /**
+ * Test constructor.
+ *
+ * @see Customize_Snapshot_Manager_Compat::__construct()
+ */
+ function test_construct_without_customize() {
+ $this->assertInstanceOf( 'CustomizeSnapshots\Customize_Snapshot_Manager_Compat', $this->manager );
+ $this->assertInstanceOf( 'CustomizeSnapshots\Plugin', $this->manager->plugin );
+ }
+
+ /**
+ * Test constructor with customizer bootstrapped.
+ *
+ * @see Customize_Snapshot_Manager_Compat::__construct()
+ */
+ function test_construct_with_customize_bootstrapped() {
+ wp_set_current_user( $this->user_id );
+ $this->do_customize_boot_actions( true );
+ unset( $GLOBALS['wp_customize'] );
+ $_REQUEST[ $this->front_param ] = self::UUID;
+ $manager = $this->get_snapshot_manager_instance( $this->plugin );
+ $manager->ensure_customize_manager();
+ $this->assertInstanceOf( 'WP_Customize_Manager', $GLOBALS['wp_customize'] );
+ }
+
+ /**
+ * Test enqueue controls scripts.
+ *
+ * @see Customize_Snapshot_Manager_Compat::enqueue_controls_scripts()
+ */
+ function test_enqueue_controls_scripts() {
+ $this->plugin->register_scripts( wp_scripts() );
+ $this->plugin->register_styles( wp_styles() );
+ $manager = $this->get_snapshot_manager_instance( $this->plugin );
+ $manager->init();
+ $manager->enqueue_controls_scripts();
+ $this->assertTrue( wp_script_is( 'customize-snapshots', 'enqueued' ) );
+ $this->assertTrue( wp_style_is( 'customize-snapshots', 'enqueued' ) );
+ }
+
+ /**
+ * Test render templates.
+ *
+ * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Compat::render_templates()
+ */
+ public function test_render_templates() {
+ ob_start();
+ $this->manager->render_templates();
+ $templates = ob_get_contents();
+ ob_end_clean();
+ $this->assertContains( 'tmpl-snapshot-dialog-error', $templates );
+ $this->assertContains( 'tmpl-snapshot-preview-link', $templates );
+ $this->assertContains( 'tmpl-snapshot-expand-button', $templates );
+ $this->assertContains( 'tmpl-snapshot-edit-container', $templates );
+ $this->assertContains( 'tmpl-snapshot-scheduled-countdown', $templates );
+ $this->assertContains( 'tmpl-snapshot-submit', $templates );
+ }
+
+ /**
+ * Test format_gmt_offset
+ *
+ * @covers \CustomizeSnapshots\Customize_Snapshot_Manager_Compat::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_Compat::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_Compat::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-customize-snapshot-manager.php b/tests/php/test-class-customize-snapshot-manager.php
index 953fa736..78ccc6dd 100644
--- a/tests/php/test-class-customize-snapshot-manager.php
+++ b/tests/php/test-class-customize-snapshot-manager.php
@@ -74,13 +74,11 @@ class Test_Customize_Snapshot_Manager extends \WP_UnitTestCase {
function setUp() {
parent::setUp();
$this->plugin = get_plugin_instance();
- if ( $this->plugin->compat ) {
- $this->front_param = 'customize_snapshot_uuid';
- } else {
- $this->front_param = 'customize_changeset_uuid';
- }
+ $this->front_param = 'customize_changeset_uuid';
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $GLOBALS['wp_customize'] = new \WP_Customize_Manager(); // WPCS: global override ok.
+ $GLOBALS['wp_customize'] = new \WP_Customize_Manager( array(
+ 'changeset_uuid' => self::UUID,
+ ) ); // WPCS: global override ok.
$this->wp_customize = $GLOBALS['wp_customize'];
$this->wp_customize->add_setting( 'foo', array( 'default' => 'foo_default' ) );
@@ -158,23 +156,10 @@ function do_customize_boot_actions( $on = false ) {
*
* @param Plugin $plugin Plugin object.
*
- * @return Customize_Snapshot_Manager|Customize_Snapshot_Manager_Back_Compat Manager new instace.
+ * @return Customize_Snapshot_Manager Manager new instace.
*/
function get_snapshot_manager_instance( $plugin ) {
- if ( $this->plugin->compat ) {
- return new Customize_Snapshot_Manager_Back_Compat( $plugin );
- } else {
- return new Customize_Snapshot_Manager( $plugin );
- }
- }
-
- /**
- * Mark test incomplete as it is only for new versions.
- */
- public function mark_incompatible() {
- if ( $this->plugin->compat ) {
- $this->markTestSkipped( 'This unit-test require WP version 4.7 or up.' );
- }
+ return new Customize_Snapshot_Manager( $plugin );
}
/**
@@ -183,30 +168,8 @@ public function mark_incompatible() {
* @see Customize_Snapshot_Manager::__construct()
*/
function test_construct_without_customize() {
- $this->mark_incompatible();
$this->assertInstanceOf( 'CustomizeSnapshots\Customize_Snapshot_Manager', $this->manager );
$this->assertInstanceOf( 'CustomizeSnapshots\Plugin', $this->manager->plugin );
- $this->assertNull( $this->manager->current_snapshot_uuid );
- }
-
- /**
- * Test constructor with Customizer.
- *
- * @see Customize_Snapshot_Manager::__construct()
- */
- function test_construct_with_customize() {
- $this->mark_incompatible();
- wp_set_current_user( $this->user_id );
- $this->do_customize_boot_actions( true );
- $this->assertTrue( is_customize_preview() );
- $_REQUEST[ $this->front_param ] = self::UUID;
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $manager->init();
- $this->assertEquals( $manager->current_snapshot_uuid, self::UUID );
- $this->assertInstanceOf( 'CustomizeSnapshots\Post_Type', $manager->post_type );
- $this->assertInstanceOf( 'CustomizeSnapshots\Customize_Snapshot', $manager->snapshot() );
- $this->assertEquals( 0, has_action( 'init', array( $manager, 'create_post_type' ) ) );
- $this->assertEquals( 10, has_action( 'customize_controls_enqueue_scripts', array( $manager, 'enqueue_controls_scripts' ) ) );
}
/**
@@ -234,13 +197,13 @@ function test_hooks() {
$manager->init();
$this->assertEquals( 10, has_action( 'init', array( $manager->post_type, 'init' ) ) );
$this->assertEquals( 10, has_action( 'customize_controls_enqueue_scripts', array( $manager, 'enqueue_controls_scripts' ) ) );
+ $this->assertEquals( 10, has_filter( 'customize_changeset_branching', '__return_true' ) );
$this->assertEquals( 10, has_action( 'admin_enqueue_scripts', array( $manager, 'enqueue_admin_scripts' ) ) );
$this->assertEquals( 10, has_action( 'customize_controls_init', array( $manager, 'add_snapshot_uuid_to_return_url' ) ) );
$this->assertEquals( 10, has_action( 'customize_controls_print_footer_scripts', array( $manager, 'render_templates' ) ) );
$this->assertEquals( 41, has_action( 'admin_bar_menu', array( $manager, 'customize_menu' ) ) );
$this->assertEquals( 100000, has_action( 'admin_bar_menu', array( $manager, 'remove_all_non_snapshot_admin_bar_links' ) ) );
$this->assertEquals( 10, has_action( 'wp_before_admin_bar_render', array( $manager, 'print_admin_bar_styles' ) ) );
- $this->assertEquals( 10, has_filter( 'removable_query_args', array( $manager, 'filter_removable_query_args' ) ) );
$this->assertEquals( 10, has_action( 'save_post_' . $manager->get_post_type(), array( $manager, 'create_initial_changeset_revision' ) ) );
$this->assertEquals( 10, has_action( 'save_post_' . $manager->get_post_type(), array( $manager, 'save_customizer_state_query_vars' ) ) );
$this->assertEquals( 10, has_filter( 'wp_insert_post_data', array( $manager, 'prepare_snapshot_post_content_for_publish' ) ) );
@@ -253,103 +216,32 @@ function test_hooks() {
* @covers \CustomizeSnapshots\Customize_Snapshot_Manager::init()
*/
public function test_init_hooks() {
- $this->mark_incompatible();
$manager = $this->get_snapshot_manager_instance( $this->plugin );
$manager->init();
$this->assertEquals( 10, has_filter( 'customize_save_response', array( $manager, 'add_snapshot_var_to_customize_save' ) ) );
$this->assertInstanceOf( __NAMESPACE__ . '\Post_Type', $manager->post_type );
}
- /**
- * Tests load_snapshot.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::load_snapshot()
- */
- public function test_load_snapshot() {
- $this->mark_incompatible();
- $manager = new Customize_Snapshot_Manager( $this->plugin );
- $this->assertNull( $manager->snapshot );
- $this->assertNull( $manager->customize_manager );
- $manager->load_snapshot();
- $this->assertInstanceOf( __NAMESPACE__ . '\\Customize_Snapshot', $manager->snapshot );
- $this->assertInstanceOf( '\WP_Customize_Manager', $manager->customize_manager );
- }
/**
* Tests add_snapshot_var_to_customize_save.
*
* @covers \CustomizeSnapshots\Customize_Snapshot_Manager::add_snapshot_var_to_customize_save()
*/
public function test_add_snapshot_var_to_customize_save() {
- $this->mark_incompatible();
global $wp_customize;
- $uuid = wp_generate_uuid4();
+ $changeset_uuid = wp_generate_uuid4();
get_plugin_instance()->customize_snapshot_manager->post_type->save( array(
- 'uuid' => $uuid,
+ 'uuid' => $changeset_uuid,
'data' => array(),
'status' => 'draft',
) );
+ $wp_customize = new \WP_Customize_Manager( compact( 'changeset_uuid' ) );
$manager = new Customize_Snapshot_Manager( $this->plugin );
- $wp_customize = null; // WPCS: global override ok.
- $manager->current_snapshot_uuid = $uuid;
- $manager->load_snapshot();
- $data = $manager->add_snapshot_var_to_customize_save( array(), $manager->customize_manager );
+ $data = $manager->add_snapshot_var_to_customize_save( array(), $manager->ensure_customize_manager() );
$this->assertArrayHasKey( 'edit_link', $data );
- $this->assertArrayHasKey( 'publish_date', $data );
$this->assertArrayHasKey( 'title', $data );
}
- /**
- * Tests enqueue_admin_scripts.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::enqueue_admin_scripts()
- */
- public function test_enqueue_admin_scripts() {
- $this->markTestIncomplete();
- }
-
- /**
- * Tests init hooks.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::init()
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::read_current_snapshot_uuid()
- */
- public function test_read_current_snapshot_uuid() {
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $manager->init();
-
- $this->assertFalse( $manager->read_current_snapshot_uuid() );
- $this->assertNull( $manager->current_snapshot_uuid );
-
- $_REQUEST[ $manager->get_customize_uuid_param() ] = 'bad';
- $this->assertFalse( $manager->read_current_snapshot_uuid() );
- $this->assertNull( $manager->current_snapshot_uuid );
-
- $_REQUEST[ $manager->get_customize_uuid_param() ] = self::UUID;
- $this->assertTrue( $manager->read_current_snapshot_uuid() );
- $this->assertEquals( self::UUID, $manager->current_snapshot_uuid );
-
- $_REQUEST[ $manager->get_customize_uuid_param() ] = self::UUID;
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $manager->init();
- $this->assertEquals( self::UUID, $manager->current_snapshot_uuid );
- }
-
- /**
- * Tests doing_customize_save_ajax.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::doing_customize_save_ajax()
- */
- public function test_doing_customize_save_ajax() {
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $this->assertFalse( $manager->doing_customize_save_ajax() );
-
- $_REQUEST['action'] = 'foo';
- $this->assertFalse( $manager->doing_customize_save_ajax() );
-
- $_REQUEST['action'] = 'customize_save';
- $this->assertTrue( $manager->doing_customize_save_ajax() );
- }
-
/**
* Tests ensure_customize_manager.
*
@@ -358,26 +250,10 @@ public function test_doing_customize_save_ajax() {
public function test_ensure_customize_manager() {
global $wp_customize;
$wp_customize = null; // WPCS: global override ok.
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $this->assertEmpty( $manager->customize_manager );
- $manager->ensure_customize_manager();
- $this->assertInstanceOf( 'WP_Customize_Manager', $manager->customize_manager );
- $this->assertInstanceOf( 'WP_Customize_Manager', $wp_customize );
- }
-
- /**
- * Tests is_theme_active.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::is_theme_active()
- */
- public function test_is_theme_active() {
- global $wp_customize;
- $wp_customize = null; // WPCS: global override ok.
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $this->assertTrue( $manager->is_theme_active() );
-
- $manager->ensure_customize_manager();
- $this->assertTrue( $manager->is_theme_active() );
+ $snapshot_manager = $this->get_snapshot_manager_instance( $this->plugin );
+ $customize_manager = $snapshot_manager->ensure_customize_manager();
+ $this->assertInstanceOf( 'WP_Customize_Manager', $customize_manager );
+ $this->assertSame( $customize_manager, $wp_customize );
}
/**
@@ -386,19 +262,21 @@ public function test_is_theme_active() {
* @see Customize_Snapshot_Manager::add_snapshot_uuid_to_return_url()
*/
public function test_add_snapshot_uuid_to_return_url() {
- global $wp_version;
- if ( version_compare( $wp_version, '4.4-beta', '>=' ) ) {
- wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
- $_GET[ $this->front_param ] = self::UUID;
- $_REQUEST[ $this->front_param ] = self::UUID;
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $manager->init();
- $manager->ensure_customize_manager();
- do_action( 'setup_theme' );
- $this->assertNotContains( $this->front_param, $manager->customize_manager->get_return_url() );
- $manager->add_snapshot_uuid_to_return_url();
- $this->assertContains( $this->front_param, $manager->customize_manager->get_return_url() );
- }
+ global $wp_customize;
+ wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
+
+ $manager = $this->get_snapshot_manager_instance( $this->plugin );
+ $wp_customize = $manager->ensure_customize_manager();
+ $_SERVER['HTTP_REFERER'] = wp_slash( add_query_arg(
+ 'customize_changeset_uuid',
+ $wp_customize->changeset_uuid(),
+ home_url( '/' )
+ ) );
+ $wp_customize->start_previewing_theme();
+ $wp_customize->set_return_url( home_url( '/' ) );
+ $this->assertNotContains( $this->front_param, $wp_customize->get_return_url() );
+ $manager->add_snapshot_uuid_to_return_url();
+ $this->assertContains( $this->front_param, $wp_customize->get_return_url() );
}
/**
@@ -429,18 +307,6 @@ function test_enqueue_controls_scripts() {
$this->assertTrue( wp_style_is( 'customize-snapshots', 'enqueued' ) );
}
- /**
- * Test snapshot method.
- *
- * @see Customize_Snapshot_Manager::snapshot()
- */
- function test_snapshot() {
- $_REQUEST[ $this->front_param ] = self::UUID;
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $manager->init();
- $this->assertInstanceOf( 'CustomizeSnapshots\Customize_Snapshot', $manager->snapshot() );
- }
-
/**
* Test prepare_snapshot_post_content_for_publish.
*
@@ -471,16 +337,6 @@ public function test_prepare_snapshot_post_content_for_publish() {
$this->assertEquals( $validate_data, json_decode( wp_unslash( $data_without_errors['post_content'] ), true ) );
}
- /**
- * Test adding snapshot_error_on_publish to removable_query_args.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::filter_removable_query_args()
- */
- public function test_filter_removable_query_args() {
- $manager = $this->get_snapshot_manager_instance( $this->plugin );
- $this->assertContains( 'snapshot_error_on_publish', $manager->filter_removable_query_args( array() ) );
- }
-
/**
* Test prepare_errors_for_response.
*
@@ -490,15 +346,6 @@ public function test_prepare_errors_for_response() {
$this->markTestIncomplete();
}
- /**
- * Tests generate_uuid.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::generate_uuid()
- */
- public function test_generate_uuid() {
- $this->markTestIncomplete();
- }
-
/**
* Tests is_valid_uuid.
*
@@ -583,10 +430,19 @@ public function test_add_post_edit_and_exit_links() {
remove_all_actions( 'admin_bar_menu' );
$manager = $this->get_snapshot_manager_instance( $this->plugin );
$_REQUEST[ $this->front_param ] = self::UUID;
- if ( ! $this->plugin->compat ) {
- global $wp_customize;
- $wp_customize = null; // WPCS: Override OK.
- }
+
+ global $wp_customize;
+ $wp_customize = $manager->ensure_customize_manager(); // WPCS: Override OK.
+ $wp_customize->start_previewing_theme();
+ $wp_customize->register_controls();
+ $wp_customize->save_changeset_post( array(
+ 'data' => array(
+ 'blogname' => array(
+ 'value' => 'Blogname',
+ ),
+ ),
+ ) );
+
$manager->init();
$wp_admin_bar = new \WP_Admin_Bar(); // WPCS: Override OK.
$wp_admin_bar->initialize();
@@ -609,48 +465,8 @@ public function test_render_templates() {
$templates = ob_get_contents();
ob_end_clean();
$this->assertContains( 'tmpl-snapshot-dialog-error', $templates );
- $this->assertContains( 'tmpl-snapshot-preview-link', $templates );
- $this->assertContains( 'tmpl-snapshot-expand-button', $templates );
- $this->assertContains( 'tmpl-snapshot-edit-container', $templates );
+ $this->assertContains( 'tmpl-snapshot-inspect-link-control', $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' );
}
/**
@@ -659,12 +475,7 @@ public function test_override_post_date_default_data() {
* @covers \CustomizeSnapshots\Customize_Snapshot_Manager::get_post_type()
*/
public function test_get_post_type() {
- $plugin = get_plugin_instance();
- if ( $plugin->compat ) {
- $this->assertEquals( $this->manager->get_post_type(), Post_Type_Back_Compat::SLUG );
- } else {
- $this->assertEquals( $this->manager->get_post_type(), Post_Type::SLUG );
- }
+ $this->assertEquals( $this->manager->get_post_type(), Post_Type::SLUG );
}
/**
@@ -673,12 +484,7 @@ public function test_get_post_type() {
* @covers \CustomizeSnapshots\Customize_Snapshot_Manager::get_front_uuid_param()
*/
public function test_get_front_uuid_param() {
- $plugin = get_plugin_instance();
- if ( $plugin->compat ) {
- $this->assertEquals( $this->manager->get_front_uuid_param(), Post_Type_Back_Compat::FRONT_UUID_PARAM_NAME );
- } else {
- $this->assertEquals( $this->manager->get_front_uuid_param(), Post_Type::FRONT_UUID_PARAM_NAME );
- }
+ $this->assertEquals( $this->manager->get_front_uuid_param(), Post_Type::FRONT_UUID_PARAM_NAME );
}
/**
@@ -687,12 +493,7 @@ public function test_get_front_uuid_param() {
* @covers \CustomizeSnapshots\Customize_Snapshot_Manager::get_customize_uuid_param()
*/
public function test_get_customize_uuid_param() {
- $plugin = get_plugin_instance();
- if ( $plugin->compat ) {
- $this->assertEquals( $this->manager->get_customize_uuid_param(), Post_Type_Back_Compat::CUSTOMIZE_UUID_PARAM_NAME );
- } else {
- $this->assertEquals( $this->manager->get_customize_uuid_param(), Post_Type::CUSTOMIZE_UUID_PARAM_NAME );
- }
+ $this->assertEquals( $this->manager->get_customize_uuid_param(), Post_Type::CUSTOMIZE_UUID_PARAM_NAME );
}
/**
@@ -714,6 +515,7 @@ public function test_replace_customize_link() {
$manager = $this->get_snapshot_manager_instance( $this->plugin );
$manager->init();
+ $manager->ensure_customize_manager()->start_previewing_theme();
// Ensure customize link remains unknown if user lacks cap.
wp_set_current_user( 0 );
@@ -795,7 +597,7 @@ public function test_save_customizer_state_query_vars() {
/**
* Test clean_up_nav_menus_created_auto_drafts
*
- * @convers \CustomizeSnapshots\Customize_Snapshot_Manager::clean_up_nav_menus_created_auto_drafts()
+ * @covers \CustomizeSnapshots\Customize_Snapshot_Manager::clean_up_nav_menus_created_auto_drafts()
*/
public function test_clean_up_nav_menus_created_auto_drafts() {
$nav_created_post_ids = $this->factory()->post->create_many( 2, array(
@@ -810,12 +612,12 @@ public function test_clean_up_nav_menus_created_auto_drafts() {
'role' => 'administrator',
) ) );
$post_id = $this->manager->post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'data' => $data,
'status' => 'draft',
) );
$copy_post_id = $this->manager->post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'data' => $data,
'status' => 'draft',
) );
diff --git a/tests/php/test-class-customize-snapshot.php b/tests/php/test-class-customize-snapshot.php
deleted file mode 100644
index fe934942..00000000
--- a/tests/php/test-class-customize-snapshot.php
+++ /dev/null
@@ -1,155 +0,0 @@
-plugin = get_plugin_instance();
- $this->mark_incompatible();
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $GLOBALS['wp_customize'] = new \WP_Customize_Manager( array( 'changeset_uuid' => self::UUID ) ); // WPCS: override ok.
- $this->snapshot_manager = new Customize_Snapshot_Manager( $this->plugin );
- $this->snapshot_manager->post_type = new Post_Type( $this->snapshot_manager );
- $this->wp_customize = $GLOBALS['wp_customize'];
- }
-
- /**
- * Tear down.
- */
- function tearDown() {
- $this->wp_customize = null;
- unset( $GLOBALS['wp_customize'] );
- unset( $GLOBALS['wp_scripts'] );
- parent::tearDown();
- }
-
- /**
- * Test UUID.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot::uuid()
- */
- function test_uuid() {
- $_REQUEST['customize_changeset_uuid'] = self::UUID;
- $manager = new Customize_Snapshot_Manager( $this->plugin );
- $manager->init();
- $this->assertEquals( self::UUID, $manager->snapshot()->uuid() );
- }
-
- /**
- * Test get_edit_link.
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot::get_edit_link()
- */
- function test_get_edit_link() {
- wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
- $post_id = $this->snapshot_manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'status' => 'draft',
- 'data' => array(),
- ) );
- $has_filter = has_filter( 'get_edit_post_link', '__return_empty_string' );
- if ( ! $has_filter ) {
- add_filter( 'get_edit_post_link', '__return_empty_string' );
- }
- $snapshot = new Customize_Snapshot( $this->snapshot_manager );
- $link = $snapshot->get_edit_link( $post_id );
- $this->assertContains( 'post=' . $post_id, $link );
- }
-
- /**
- * Test post
- *
- * @covers \CustomizeSnapshots\Customize_Snapshot::post()
- */
- function test_post() {
- $post_id = $this->snapshot_manager->post_type->save( array(
- 'uuid' => self::UUID,
- 'status' => 'draft',
- 'data' => array(),
- ) );
- $this->snapshot_manager->customize_manager = new \WP_Customize_Manager( array(
- 'changeset_uuid' => self::UUID,
- ) );
- $snapshot = new Customize_Snapshot( $this->snapshot_manager );
- $snapshot_post = $snapshot->post();
- $this->assertEquals( $post_id, $snapshot_post->ID );
- $this->snapshot_manager->customize_manager = new \WP_Customize_Manager( array(
- 'changeset_uuid' => wp_generate_uuid4(),
- ) );
- $snapshot_post = $snapshot->post();
- $this->assertNull( $snapshot_post );
- }
-
- /**
- * Mark test incomplete as it is only for new versions.
- */
- public function mark_incompatible() {
- if ( $this->plugin->compat ) {
- $this->markTestSkipped( 'This unit-test require WP version 4.7 or up.' );
- }
- }
-}
diff --git a/tests/php/test-class-migrate.php b/tests/php/test-class-migrate.php
deleted file mode 100644
index 204da93b..00000000
--- a/tests/php/test-class-migrate.php
+++ /dev/null
@@ -1,263 +0,0 @@
-plugin = get_plugin_instance();
- $this->mark_incompatible();
- $this->snapshot_manager = new Customize_Snapshot_Manager( $this->plugin );
- $this->snapshot_manager->post_type = new Post_Type( $this->snapshot_manager );
- }
-
- /**
- * Mark test incomplete as it is only for new versions.
- */
- public function mark_incompatible() {
- if ( $this->plugin->compat ) {
- $this->markTestSkipped( 'This unit-test require WP version 4.7 or up.' );
- }
- }
-
- /**
- * Tear down.
- */
- function tearDown() {
- $this->wp_customize = null;
- unset( $GLOBALS['wp_customize'] );
- unset( $GLOBALS['wp_scripts'] );
- update_option( Migrate::KEY, 0 );
- parent::tearDown();
- }
-
- /**
- * Test Migrate constructor.
- *
- * @see Migrate::__construct()
- */
- function test_construct() {
- $class_name = 'CustomizeSnapshots\Migrate';
- $mock = $this->getMockBuilder( $class_name )
- ->disableOriginalConstructor()
- ->getMock();
- $mock->expects( $this->once() )
- ->method( 'maybe_migrate' );
- $reflected_class = new \ReflectionClass( $class_name );
- $constructor = $reflected_class->getConstructor();
- $constructor->invoke( $mock, $this->plugin );
- set_current_screen( 'index' );
- $constructor->invoke( $mock, $this->plugin );
- $user_id = $this->factory()->user->create( array(
- 'role' => 'administrator',
- ) );
- if ( is_multisite() ) {
- grant_super_admin( $user_id );
- }
- wp_set_current_user( $user_id );
- $constructor->invoke( $mock, $this->plugin );
- }
-
- /**
- * Test is_migrated.
- *
- * @see Migrate::is_migrated()
- */
- function test_is_migrated() {
- $migrate = new Migrate( $this->plugin );
- update_option( Migrate::KEY, 0 );
- $this->assertFalse( $migrate->is_migrated() );
- update_option( Migrate::KEY, 1 );
- $this->assertTrue( $migrate->is_migrated() );
- }
-
- /**
- * Test maybe_migrate.
- *
- * @see Migrate::maybe_migrate()
- */
- function test_maybe_migrate() {
- delete_option( Migrate::KEY );
- $migrate = $this->getMockBuilder( 'CustomizeSnapshots\Migrate' )
- ->setMethods( array( 'changeset_migrate' ) )
- ->setConstructorArgs( array( $this->plugin ) )
- ->getMock();
- $migrate->expects( $this->once() )
- ->method( 'changeset_migrate' )
- ->with( 1, true )
- ->will( $this->returnValue( 92 ) );
- $migrate->maybe_migrate();
- $this->assertEquals( 10, has_action( 'admin_notices', array( $migrate, 'show_migration_notice' ) ) );
- $this->assertEquals( 10, has_action( 'admin_enqueue_scripts', array( $migrate, 'enqueue_script' ) ) );
- $this->assertEquals( 10, has_action( 'wp_ajax_customize_snapshot_migration', array( $migrate, 'handle_migrate_changeset_request' ) ) );
-
- // If no post to migrate fall back and add option value.
- $migrate_obj = $this->getMockBuilder( 'CustomizeSnapshots\Migrate' )
- ->setMethods( array( 'changeset_migrate' ) )
- ->setConstructorArgs( array( $this->plugin ) )
- ->getMock();
- $migrate_obj->expects( $this->once() )
- ->method( 'changeset_migrate' )
- ->with( 1, true )
- ->will( $this->returnValue( false ) );
- $migrate_obj->maybe_migrate();
- $this->assertNotEquals( 10, has_action( 'admin_notices', array( $migrate_obj, 'show_migration_notice' ) ) );
- $this->assertNotEquals( 10, has_action( 'admin_enqueue_scripts', array( $migrate_obj, 'enqueue_script' ) ) );
- $this->assertNotEquals( 10, has_action( 'wp_ajax_customize_snapshot_migration', array( $migrate_obj, 'handle_migrate_changeset_request' ) ) );
- $this->assertEquals( 1, get_option( Migrate::KEY ) );
- }
-
- /**
- * Test show_migration_notice.
- *
- * @see Migrate::show_migration_notice()
- */
- function test_show_migration_notice() {
- $migrate = new Migrate( $this->plugin );
- ob_start();
- $migrate->show_migration_notice();
- $data = ob_get_clean();
- $this->assertContains( 'customize-snapshot-migration', $data );
- $this->assertContains( 'customize-snapshot-migration', $data );
- $this->assertContains( 'data-nonce', $data );
- $this->assertContains( 'data-migration-success', $data );
- $this->assertContains( 'customize-snapshot-spinner', $data );
- }
-
- /**
- * Test changeset_migrate.
- *
- * @see Migrate::changeset_migrate()
- */
- function test_changeset_migrate() {
- $old_post_type_obj = new Post_Type_Back_Compat( $this->snapshot_manager );
- $post_id = $old_post_type_obj->save( array(
- 'uuid' => wp_generate_uuid4(),
- 'status' => 'draft',
- 'data' => array(),
- ) );
- $migrate = new Migrate( $this->plugin );
- $posts_count = $migrate->changeset_migrate( -1, true );
- $this->assertEquals( $post_id, array_shift( $posts_count ) );
-
- $migrate_obj = $this->getMockBuilder( 'CustomizeSnapshots\Migrate' )
- ->setMethods( array( 'migrate_post' ) )
- ->setConstructorArgs( array( $this->plugin ) )
- ->getMock();
- $migrate_obj->expects( $this->once() )
- ->method( 'migrate_post' )
- ->will( $this->returnValue( null ) );
- $migrate_obj->changeset_migrate( -1 );
- }
-
- /**
- * Test migrate_post.
- *
- * @see Migrate::migrate_post()
- */
- function test_migrate_post() {
- $admin_user_id = $this->factory()->user->create( array(
- 'role' => 'administrator',
- ) );
- wp_set_current_user( $admin_user_id );
- $old_post_type_obj = new Post_Type_Back_Compat( $this->snapshot_manager );
- $snapshot_post_id = $old_post_type_obj->save( array(
- 'uuid' => wp_generate_uuid4(),
- 'status' => 'draft',
- 'data' => array(
- 'foo' => array(
- 'value' => 'bar',
- ),
- ),
- ) );
- add_post_meta( $snapshot_post_id, '_snapshot_theme', 'foo_theme' );
- require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
- $wp_customize = new \WP_Customize_Manager( array(
- 'changeset_uuid' => self::UUID,
- ) );
-
- $wp_customize->add_setting( 'foo', array(
- 'default' => 'foo_default',
- ) );
- $this->action_customize_register_for_dynamic_settings();
-
- $migrate = new Migrate( $this->plugin );
-
- $has_kses = ( false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ) );
- if ( $has_kses ) {
- kses_remove_filters(); // Prevent KSES from corrupting JSON in post_content.
- }
- $migrate->migrate_post( $snapshot_post_id );
- if ( $has_kses ) {
- kses_init_filters();
- }
-
- $changeset_post = get_post( $snapshot_post_id );
- $this->assertEquals( Post_Type::SLUG, $changeset_post->post_type );
- $data = json_decode( $changeset_post->post_content, true );
- $expected = array(
- 'foo_theme::foo' => array(
- 'value' => 'bar',
- 'user_id' => (string) $admin_user_id,
- 'type' => 'theme_mod',
- ),
- );
- $this->assertSame( $expected, $data );
- }
-
- /**
- * Add filter for dynamic setting.
- */
- function action_customize_register_for_dynamic_settings() {
- add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args_for_test_dynamic_settings' ), 10, 2 );
- }
-
- /**
- * To support dynamic setting.
- *
- * @param array $setting_args Setting args.
- * @param string $setting_id Setting ID.
- * @return array
- */
- function filter_customize_dynamic_setting_args_for_test_dynamic_settings( $setting_args, $setting_id ) {
- if ( in_array( $setting_id, array( 'foo' ), true ) ) {
- $setting_args = array(
- 'default' => "dynamic_{$setting_id}_default",
- );
- }
- return $setting_args;
- }
-}
diff --git a/tests/php/test-class-post-type-back-compat.php b/tests/php/test-class-post-type-back-compat.php
deleted file mode 100644
index fb29ccfd..00000000
--- a/tests/php/test-class-post-type-back-compat.php
+++ /dev/null
@@ -1,295 +0,0 @@
-plugin = get_plugin_instance();
- if ( ! $this->plugin->compat ) {
- $this->markTestSkipped( 'WordPress Version 4.6.x or below is required for this test-case.' );
- }
- $GLOBALS['wp_customize'] = null; // WPCS: Global override ok.
- unregister_post_type( Post_Type_Back_Compat::SLUG );
- }
-
- /**
- * Test register post type.
- *
- * @see Post_Type::init()
- */
- public function test_init() {
- $this->assertFalse( post_type_exists( Post_Type_Back_Compat::SLUG ) );
- $post_type_obj = new Post_Type_Back_Compat( $this->plugin->customize_snapshot_manager );
- $this->plugin->customize_snapshot_manager->init();
- $post_type_obj->init();
- $this->assertTrue( post_type_exists( Post_Type_Back_Compat::SLUG ) );
-
- $this->assertEquals( 10, has_action( 'admin_notices', array( $post_type_obj, 'show_publish_error_admin_notice' ) ) );
- $this->assertEquals( 10, has_filter( 'display_post_states', array( $post_type_obj, 'display_post_states' ) ) );
- $this->assertEquals( 10, has_action( 'admin_footer-edit.php', array( $post_type_obj, 'snapshot_merge_print_script' ) ) );
- $this->assertEquals( 10, has_action( 'load-edit.php', array( $post_type_obj, 'handle_snapshot_merge_workaround' ) ) );
- $this->assertEquals( 10, has_filter( 'post_type_link', array( $post_type_obj, 'filter_post_type_link' ) ) );
- $this->assertEquals( 10, has_filter( 'wp_insert_post_data', array( $post_type_obj, 'preserve_post_name_in_insert_data' ) ) );
- }
-
- /**
- * Tests show_publish_error_admin_notice.
- *
- * @covers \CustomizeSnapshots\Post_Type_Back_Compat::show_publish_error_admin_notice()
- */
- public function test_show_publish_error_admin_notice() {
- global $current_screen, $post;
- wp_set_current_user( $this->factory()->user->create( array(
- 'role' => 'administrator',
- ) ) );
- $post_type_obj = new Post_Type_Back_Compat( $this->plugin->customize_snapshot_manager );
- $post_type_obj->init();
- $post_id = $post_type_obj->save( array(
- 'uuid' => self::UUID,
- 'data' => array(),
- ) );
-
- ob_start();
- $post_type_obj->show_publish_error_admin_notice();
- $this->assertEmpty( ob_get_clean() );
-
- $current_screen = \WP_Screen::get( 'customize_snapshot' ); // WPCS: Override ok.
- $current_screen->id = 'customize_snapshot';
- $current_screen->base = 'edit';
- ob_start();
- $post_type_obj->show_publish_error_admin_notice();
- $this->assertEmpty( ob_get_clean() );
-
- $current_screen->base = 'post';
- ob_start();
- $post_type_obj->show_publish_error_admin_notice();
- $this->assertEmpty( ob_get_clean() );
-
- $_REQUEST['snapshot_error_on_publish'] = '1';
- wp_update_post( array(
- 'ID' => $post_id,
- 'post_status' => 'pending',
- ) );
- $post = get_post( $post_id ); // WPCS: override ok.
- ob_start();
- $post_type_obj->show_publish_error_admin_notice();
- $this->assertContains( 'notice-error', ob_get_clean() );
- }
-
- /**
- * Tests display_post_states.
- *
- * @covers \CustomizeSnapshots\Post_Type_Back_Compat::display_post_states()
- */
- public function test_display_post_states() {
- $post_type_obj = new Post_Type_Back_Compat( $this->plugin->customize_snapshot_manager );
-
- $post_id = $post_type_obj->save( array(
- 'uuid' => self::UUID,
- 'data' => array( 'foo' => array( 'value' => 'bar' ) ),
- ) );
- $states = $post_type_obj->display_post_states( array(), get_post( $post_id ) );
- $this->assertArrayNotHasKey( 'snapshot_error', $states );
-
- update_post_meta( $post_id, 'snapshot_error_on_publish', true );
- $states = $post_type_obj->display_post_states( array(), get_post( $post_id ) );
- $this->assertArrayHasKey( 'snapshot_error', $states );
- }
-
- /**
- * Test snapshot_merge_print_script
- *
- * @see Post_Type_Back_Compat::snapshot_merge_print_script()
- */
- public function test_snapshot_merge_print_script() {
- global $post_type;
- $post_type = Post_Type_Back_Compat::SLUG; // WPCS: global override ok.
- $post_type_obj = new Post_Type_Back_Compat( $this->plugin->customize_snapshot_manager );
- ob_start();
- $post_type_obj->snapshot_merge_print_script();
- $script_content = ob_get_clean();
-
- $this->assertContains( 'select[name="action"]', $script_content );
- $this->assertContains( 'select[name="action2"]', $script_content );
- $this->assertContains( 'merge_snapshot', $script_content );
- $this->assertContains( 'text/javascript', $script_content );
- }
-
- /**
- * Test handle_snapshot_bulk_actions_workaround
- *
- * @see Post_Type_Back_Compat::handle_snapshot_merge_workaround()
- */
- public function test_handle_snapshot_bulk_actions_workaround() {
- $GLOBALS['hook_suffix'] = 'posts-' . Post_Type_Back_Compat::SLUG; // WPCS: global override ok.
- $_POST['action'] = $_REQUEST['action'] = $_GET['action'] = 'merge_snapshot';
- $_POST['post_type'] = $_REQUEST['post_type'] = $_GET['post_type'] = Post_Type_Back_Compat::SLUG;
- $_POST['post'] = $_REQUEST['post'] = $_GET['post'] = array( 1, 2 );
- $_POST['_wpnonce'] = $_REQUEST['_wpnonce'] = $_GET['_wpnonce'] = wp_create_nonce( 'bulk-posts' );
- $_POST['_wp_http_referer'] = $_REQUEST['_wp_http_referer'] = $_GET['_wp_http_referer'] = admin_url();
- $post_type_obj = $this->getMockBuilder( 'CustomizeSnapshots\Post_Type_Back_Compat' )
- ->setConstructorArgs( array( $this->plugin->customize_snapshot_manager ) )
- ->setMethods( array( 'handle_snapshot_merge' ) )
- ->getMock();
- $post_type_obj->expects( $this->once() )
- ->method( 'handle_snapshot_merge' )
- ->will( $this->returnValue( null ) );
- $post_type_obj->handle_snapshot_merge_workaround();
- }
-
- /**
- * Tests preservation of the post_name when submitting a snapshot for review.
- *
- * @see Post_Type_Back_Compat::preserve_post_name_in_insert_data()
- */
- public function test_preserve_post_name_in_insert_data() {
- $post_type_obj = new Post_Type_Back_Compat( $this->plugin->customize_snapshot_manager );
- $post_type_obj->init();
-
- $post_data = array(
- 'post_name' => '',
- 'post_type' => 'no',
- 'post_status' => 'pending',
- );
- $original_post_data = array(
- 'post_type' => 'no',
- 'post_name' => '!original!',
- 'post_status' => 'pending',
- );
- $filtered_post_data = $post_type_obj->preserve_post_name_in_insert_data( $post_data, $original_post_data );
- $this->assertEquals( $post_data, $filtered_post_data );
-
- $post_data['post_type'] = Post_Type_Back_Compat::SLUG;
- $original_post_data['post_type'] = Post_Type_Back_Compat::SLUG;
-
- $filtered_post_data = $post_type_obj->preserve_post_name_in_insert_data( $post_data, $original_post_data );
- $this->assertEquals( $original_post_data['post_name'], $filtered_post_data['post_name'] );
- }
-
- /**
- * Snapshot publish.
- *
- * @see Post_Type::save()
- */
- function test_publish_snapshot() {
- $admin_user_id = $this->factory()->user->create( array(
- 'role' => 'administrator',
- ) );
- wp_set_current_user( $admin_user_id );
- $post_type = get_plugin_instance()->customize_snapshot_manager->post_type;
- $post_type->init();
- $tag_line = 'Snapshot blog';
-
- $data = array(
- 'blogdescription' => array(
- 'value' => $tag_line,
- ),
- 'foo' => array(
- 'value' => 'bar',
- ),
- 'baz' => array(
- 'value' => null,
- ),
- );
-
- $validated_content = array(
- 'blogdescription' => array(
- 'value' => $tag_line,
- ),
- 'foo' => array(
- 'value' => 'bar',
- 'publish_error' => 'unrecognized_setting',
- ),
- 'baz' => array(
- 'value' => null,
- 'publish_error' => 'null_value',
- ),
- );
-
- /*
- * Ensure that directly updating a post succeeds with invalid settings
- * works because the post is a draft. Note that if using
- * Customize_Snapshot::set() this would fail because it does validation.
- */
- $post_id = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
- 'data' => $data,
- 'status' => 'draft',
- ) );
- wp_update_post( array(
- 'ID' => $post_id,
- 'post_status' => 'draft',
- ) );
- $content = $post_type->get_post_content( get_post( $post_id ) );
- $this->assertEquals( $data, $content );
-
- /*
- * Ensure that attempting to publish a snapshot with invalid settings
- * will get the publish_errors added as well as kick it back to pending.
- */
- remove_all_filters( 'redirect_post_location' );
- $post_id = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
- 'data' => $data,
- 'status' => 'draft',
- ) );
- wp_publish_post( $post_id );
- $snapshot_post = get_post( $post_id );
- $content = $post_type->get_post_content( $snapshot_post );
- $this->assertEquals( 'pending', $snapshot_post->post_status );
- $this->assertEquals( $validated_content, $content );
- $this->assertContains(
- 'snapshot_error_on_publish=1',
- apply_filters( 'redirect_post_location', get_edit_post_link( $snapshot_post->ID ), $snapshot_post->ID )
- );
-
- /*
- * Remove invalid settings and now attempt publish.
- */
- remove_all_filters( 'redirect_post_location' );
- unset( $data['foo'] );
- unset( $data['baz'] );
- $post_id = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
- 'data' => $data,
- 'status' => 'draft',
- ) );
- wp_publish_post( $post_id );
- $snapshot_post = get_post( $post_id );
- $content = $post_type->get_post_content( $snapshot_post );
- $this->assertEquals( 'publish', $snapshot_post->post_status );
- $this->assertEquals( $data, $content );
- $this->assertEquals( $tag_line, get_bloginfo( 'description' ) );
- $this->assertNotContains(
- 'snapshot_error_on_publish=1',
- apply_filters( 'redirect_post_location', get_edit_post_link( $snapshot_post->ID ), $snapshot_post->ID )
- );
- }
-}
diff --git a/tests/php/test-class-post-type.php b/tests/php/test-class-post-type.php
index 471d0c8e..a2aecec6 100644
--- a/tests/php/test-class-post-type.php
+++ b/tests/php/test-class-post-type.php
@@ -40,35 +40,18 @@ function setUp() {
parent::setUp();
$GLOBALS['wp_customize'] = null; // WPCS: Global override ok.
$this->plugin = get_plugin_instance();
- if ( $this->plugin->compat ) {
- $this->post_type_slug = Post_Type_Back_Compat::SLUG;
- } else {
- $this->post_type_slug = Post_Type::SLUG;
- }
+ $this->post_type_slug = Post_Type::SLUG;
}
/**
* Get plugin instance accoding to WP version.
*
- * @param Customize_Snapshot_Manager|Customize_Snapshot_Manager_Back_Compat $manager Manager.
+ * @param Customize_Snapshot_Manager $manager Manager.
*
- * @return Post_Type|Post_Type_Back_Compat Post type object.
+ * @return Post_Type Post type object.
*/
public function get_new_post_type_instance( $manager ) {
- if ( $this->plugin->compat ) {
- return new Post_Type_Back_Compat( $manager );
- } else {
- return new Post_Type( $manager );
- }
- }
-
- /**
- * Mark test incomplete as it is only for new versions.
- */
- public function mark_incompatible() {
- if ( $this->plugin->compat ) {
- $this->markTestSkipped( 'This unit-test require WP version 4.7 or up.' );
- }
+ return new Post_Type( $manager );
}
/**
@@ -77,7 +60,6 @@ public function mark_incompatible() {
* @see Post_Type::init()
*/
public function test_init() {
- $this->mark_incompatible();
$post_type_obj = $this->get_new_post_type_instance( $this->plugin->customize_snapshot_manager );
$this->plugin->customize_snapshot_manager->init();
$post_type_obj->init();
@@ -88,7 +70,6 @@ public function test_init() {
$this->assertEquals( 5, has_filter( 'map_meta_cap', array( $post_type_obj, 'remap_customize_meta_cap' ) ) );
$this->assertEquals( 10, has_filter( 'bulk_actions-edit-' . Post_Type::SLUG, array( $post_type_obj, 'add_snapshot_bulk_actions' ) ) );
$this->assertEquals( 10, has_filter( 'handle_bulk_actions-edit-' . Post_Type::SLUG, array( $post_type_obj, 'handle_snapshot_merge' ) ) );
- $this->assertEquals( 10, has_action( 'admin_print_styles-edit.php', array( $post_type_obj, 'hide_add_new_changeset_button' ) ) );
}
/**
@@ -110,6 +91,8 @@ public function test_hooks() {
$this->assertEquals( 10, has_filter( 'content_save_pre', array( $post_type_obj, 'filter_out_settings_if_removed_in_metabox' ) ) );
$this->assertEquals( 10, has_action( 'admin_print_scripts-revision.php', array( $post_type_obj, 'disable_revision_ui_for_published_posts' ) ) );
$this->assertEquals( 10, has_action( 'admin_notices', array( $post_type_obj, 'admin_show_merge_error' ) ) );
+ $this->assertEquals( 10, has_filter( 'display_post_states', array( $post_type_obj, 'display_post_states' ) ) );
+ $this->assertEquals( 10, has_action( 'admin_notices', array( $post_type_obj, 'show_publish_error_admin_notice' ) ) );
}
/**
@@ -119,7 +102,6 @@ public function test_hooks() {
*/
public function test_extend_changeset_post_type_object() {
global $_wp_post_type_features;
- $this->mark_incompatible();
$post_type_obj = get_post_type_object( Post_Type::SLUG );
$this->assertArrayHasKey( 'revisions', $_wp_post_type_features[ Post_Type::SLUG ] );
$this->assertTrue( $post_type_obj->show_ui );
@@ -158,7 +140,7 @@ function test_force_at_least_one_revision() {
),
);
$post_id = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'data' => $data,
'status' => 'draft',
) );
@@ -176,7 +158,6 @@ function test_force_at_least_one_revision() {
* @covers \CustomizeSnapshots\Post_Type::add_admin_menu_item()
*/
public function test_add_admin_menu_item() {
- $this->mark_incompatible();
global $submenu, $menu;
$menu = $submenu = array(); // WPCS: global override ok.
$admin_user_id = $this->factory()->user->create( array(
@@ -282,7 +263,10 @@ public function test_setup_metaboxes() {
$post_type = $this->get_new_post_type_instance( $this->plugin->customize_snapshot_manager );
$post_type->init();
- $post_id = $this->factory()->post->create( array( 'post_type' => $this->post_type_slug, 'post_status' => 'draft' ) );
+ $post_id = $this->factory()->post->create( array(
+ 'post_type' => $this->post_type_slug,
+ 'post_status' => 'draft',
+ ) );
$wp_meta_boxes = array(); // WPCS: global override ok.
$metabox_id = $this->post_type_slug;
@@ -483,7 +467,6 @@ function filter_customize_snapshot_value_preview( $preview, $context ) {
* Find a snapshot post by UUID.
*
* @see Post_Type::find_post()
- * @see Post_Type_Back_Compat::find_post()
*/
public function test_find_post() {
$post_type = $this->get_new_post_type_instance( $this->plugin->customize_snapshot_manager );
@@ -546,9 +529,7 @@ public function test_get_post_content() {
'status' => 'publish',
) );
$snapshot_post = get_post( $post_id );
- if ( ! $this->plugin->compat ) {
- unset( $data['foo']['publish_error'] );
- }
+ unset( $data['foo']['publish_error'] );
$this->assertEquals( $data, $post_type->get_post_content( $snapshot_post ) );
// Revision.
@@ -566,7 +547,10 @@ public function test_get_post_content() {
$this->assertEquals( 'baz', $content['foo']['value'] );
// Bad post data.
- $bad_post_id = $this->factory()->post->create( array( 'post_type' => $this->post_type_slug, 'post_content' => 'BADJSON' ) );
+ $bad_post_id = $this->factory()->post->create( array(
+ 'post_type' => $this->post_type_slug,
+ 'post_content' => 'BADJSON',
+ ) );
$bad_post = get_post( $bad_post_id );
$content = $post_type->get_post_content( $bad_post );
$this->assertEquals( array(), $content );
@@ -590,17 +574,28 @@ public function test_save() {
$this->assertInstanceOf( 'WP_Error', $r );
$this->assertEquals( 'missing_valid_uuid', $r->get_error_code() );
- $r = $post_type->save( array( 'uuid' => self::UUID, 'data' => 'bad' ) );
+ $r = $post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => 'bad',
+ ) );
$this->assertInstanceOf( 'WP_Error', $r );
$this->assertEquals( 'missing_data', $r->get_error_code() );
// Error: bad_setting_params.
- $r = $post_type->save( array( 'uuid' => self::UUID, 'data' => array( 'foo' => 'bar' ) ) );
+ $r = $post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array( 'foo' => 'bar' ),
+ ) );
$this->assertInstanceOf( 'WP_Error', $r );
$this->assertEquals( 'bad_setting_params', $r->get_error_code() );
// Error: missing_value_param.
- $r = $post_type->save( array( 'uuid' => self::UUID, 'data' => array( 'foo' => array( 'bar' => 'quux' ) ) ) );
+ $r = $post_type->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array(
+ 'foo' => array( 'bar' => 'quux' ),
+ ),
+ ) );
$this->assertInstanceOf( 'WP_Error', $r );
$this->assertEquals( 'missing_value_param', $r->get_error_code() );
@@ -635,9 +630,7 @@ public function test_save() {
) );
$this->assertInternalType( 'int', $r );
$expected = $data;
- if ( ! $this->plugin->compat ) {
- unset( $expected['foo']['publish_error'] );
- }
+ unset( $expected['foo']['publish_error'] );
$this->assertEquals( $expected, $post_type->get_post_content( get_post( $r ) ) );
$this->assertEquals( get_stylesheet(), get_post_meta( $r, '_snapshot_theme', true ) );
@@ -805,12 +798,14 @@ public function test_add_snapshot_bulk_actions() {
public function test_handle_snapshot_merge() {
$ids = $this->factory()->post->create_many( 2 );
$posts = array_map( 'get_post', $ids );
- $post_type_obj = $this->getMockBuilder( 'CustomizeSnapshots\Post_Type' )
- ->setConstructorArgs( array( $this->plugin->customize_snapshot_manager ) )
- ->setMethods( array( 'merge_snapshots' ) )
- ->getMock();
- $post_type_obj->expects( $this->once() )
- ->method( 'merge_snapshots' )
+ $post_type_obj = $this
+ ->getMockBuilder( 'CustomizeSnapshots\Post_Type' )
+ ->setConstructorArgs( array( $this->plugin->customize_snapshot_manager ) )
+ ->setMethods( array( 'merge_snapshots' ) )
+ ->getMock();
+ $post_type_obj
+ ->expects( $this->once() )
+ ->method( 'merge_snapshots' )
->with( $posts )
->will( $this->returnValue( null ) );
$post_type_obj->handle_snapshot_merge( '', 'merge_snapshot', $ids );
@@ -825,7 +820,7 @@ public function test_merge_snapshots() {
$post_type = $this->get_new_post_type_instance( $this->plugin->customize_snapshot_manager );
$date1 = gmdate( 'Y-m-d H:i:s' );
$post_1 = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'status' => 'draft',
'data' => array(
'foo' => array(
@@ -844,7 +839,7 @@ public function test_merge_snapshots() {
);
$date2 = gmdate( 'Y-m-d H:i:s', ( time() + 60 ) );
$post_2 = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'status' => 'draft',
'data' => $value,
'date_gmt' => $date2,
@@ -872,7 +867,7 @@ public function test_merge_snapshots() {
),
);
$post_3 = $post_type->save( array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'status' => 'draft',
'data' => $value_3,
'date_gmt' => $date3,
@@ -955,25 +950,72 @@ public function test_filter_out_settings_if_removed_in_metabox() {
* @covers \CustomizeSnapshots\Post_Type::remap_customize_meta_cap()
*/
public function test_remap_customize_meta_cap() {
- $this->mark_incompatible();
$this->markTestIncomplete();
}
/**
- * Test hide_add_new_changeset_button
+ * Tests display_post_states.
*
- * @covers \CustomizeSnapshots\Post_Type::hide_add_new_changeset_button()
+ * @covers \CustomizeSnapshots\Post_Type::display_post_states()
*/
- public function test_hide_add_new_changeset_button() {
- $this->mark_incompatible();
+ public function test_display_post_states() {
$post_type_obj = new Post_Type( $this->plugin->customize_snapshot_manager );
- global $typenow;
- $typenow = Post_Type::SLUG; // WPCS: Global override ok.
- ob_start();
- $post_type_obj->hide_add_new_changeset_button();
- $content = ob_get_clean();
- $this->assertContains( 'a.page-title-action', $content );
- $this->assertContains( 'display: none;', $content );
+
+ $post_id = $post_type_obj->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array( 'foo' => array( 'value' => 'bar' ) ),
+ ) );
+ $states = $post_type_obj->display_post_states( array(), get_post( $post_id ) );
+ $this->assertArrayNotHasKey( 'snapshot_error', $states );
+
+ update_post_meta( $post_id, 'snapshot_error_on_publish', true );
+ $states = $post_type_obj->display_post_states( array(), get_post( $post_id ) );
+ $this->assertArrayHasKey( 'snapshot_error', $states );
}
+ /**
+ * Tests 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;
+ wp_set_current_user( $this->factory()->user->create( array(
+ 'role' => 'administrator',
+ ) ) );
+ $post_type_obj = new Post_Type( $this->plugin->customize_snapshot_manager );
+ $post_type_obj->init();
+ $post_id = $post_type_obj->save( array(
+ 'uuid' => self::UUID,
+ 'data' => array(),
+ ) );
+
+ ob_start();
+ $post_type_obj->show_publish_error_admin_notice();
+ $this->assertEmpty( ob_get_clean() );
+
+ $current_screen = \WP_Screen::get( 'customize_snapshot' ); // WPCS: Override ok.
+ $current_screen->id = 'customize_snapshot';
+ $current_screen->base = 'edit';
+ ob_start();
+ $post_type_obj->show_publish_error_admin_notice();
+ $this->assertEmpty( ob_get_clean() );
+
+ $current_screen->base = 'post';
+ ob_start();
+ $post_type_obj->show_publish_error_admin_notice();
+ $this->assertEmpty( ob_get_clean() );
+
+ $_REQUEST['snapshot_error_on_publish'] = '1';
+ wp_update_post( array(
+ 'ID' => $post_id,
+ 'post_status' => 'pending',
+ ) );
+ $post = get_post( $post_id ); // WPCS: override ok.
+ ob_start();
+ $post_type_obj->show_publish_error_admin_notice();
+
+ $this->markTestIncomplete();
+ $this->assertContains( 'notice-error', ob_get_clean() ); // @todo Test failing.
+ }
}
diff --git a/tests/php/test-class-snapshot-ajax.php b/tests/php/test-class-snapshot-ajax.php
deleted file mode 100644
index 64b16546..00000000
--- a/tests/php/test-class-snapshot-ajax.php
+++ /dev/null
@@ -1,83 +0,0 @@
-plugin = get_plugin_instance();
- if ( $this->plugin->compat ) {
- $this->markTestSkipped( 'This unit-test require WP version 4.7 or up.' );
- }
- parent::setUp();
- }
- /**
- * Test handle_migrate_changeset_request.
- *
- * @see Migrate::handle_migrate_changeset_request()
- */
- function test_handle_migrate_changeset_request() {
- remove_all_actions( 'wp_ajax_customize_snapshot_migration' );
- delete_option( Migrate::KEY );
- $migrate_obj = $this->getMockBuilder( 'CustomizeSnapshots\Migrate' )
- ->setMethods( array( 'changeset_migrate' ) )
- ->setConstructorArgs( array( $this->plugin ) )
- ->getMock();
- $migrate_obj->expects( $this->any() )
- ->method( 'changeset_migrate' )
- ->will( $this->returnValue( 92 ) );
- $migrate_obj->maybe_migrate();
- $this->set_input_vars(array(
- 'nonce' => wp_create_nonce( 'customize-snapshot-migration' ),
- 'limit' => 1,
- ));
- $this->make_ajax_call( 'customize_snapshot_migration' );
- $response = json_decode( $this->_last_response, true );
- $this->assertTrue( $response['success'] );
- $this->assertArrayHasKey( 'remaining_posts', $response['data'] );
- $this->assertEquals( 91, $response['data']['remaining_posts'] );
- }
-
- /**
- * Helper to keep it DRY
- *
- * @param string $action Action.
- */
- protected function make_ajax_call( $action ) {
- try {
- $this->_handleAjax( $action );
- } catch ( \WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- }
-
- /**
- * Set input vars.
- *
- * @param array $vars Input vars.
- * @param string $method Request method.
- */
- public function set_input_vars( array $vars = array(), $method = 'POST' ) {
- $_GET = $_POST = $_REQUEST = wp_slash( $vars );
- $_SERVER['REQUEST_METHOD'] = $method;
- }
-
-}
diff --git a/tests/php/test-class-snapshot-rest-api-controller.php b/tests/php/test-class-snapshot-rest-api-controller.php
index 0b51c1e7..fee0a294 100644
--- a/tests/php/test-class-snapshot-rest-api-controller.php
+++ b/tests/php/test-class-snapshot-rest-api-controller.php
@@ -47,11 +47,7 @@ function setUp() {
parent::setUp();
$this->plugin = get_plugin_instance();
- if ( $this->plugin->compat ) {
- $this->end_point = 'customize_snapshots';
- } else {
- $this->end_point = 'customize_changesets';
- }
+ $this->end_point = 'customize_changesets';
$this->plugin->customize_snapshot_manager->post_type->init();
@@ -78,7 +74,7 @@ function setUp() {
$post_id = $this->plugin->customize_snapshot_manager->post_type->save( array_merge(
$snapshot_params,
array(
- 'uuid' => Customize_Snapshot_Manager::generate_uuid(),
+ 'uuid' => wp_generate_uuid4(),
'author' => $user_id,
'data' => array( 'blogname' => array( 'value' => "Snapshot $i" ) ),
)
@@ -234,7 +230,7 @@ function test_create_item() {
wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
$request = new \WP_REST_Request( 'POST', '/wp/v2/' . $this->end_point );
$request->set_param( 'content', array( 'blogname' => array( 'value' => 'test' ) ) );
- $request->set_param( 'slug', Customize_Snapshot_Manager::generate_uuid() );
+ $request->set_param( 'slug', wp_generate_uuid4() );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_create', $response );
}
diff --git a/tests/test-customize-snapshots.php b/tests/test-customize-snapshots.php
index cbbfb1a0..0ce25928 100644
--- a/tests/test-customize-snapshots.php
+++ b/tests/test-customize-snapshots.php
@@ -24,11 +24,7 @@ class Test_Customize_Snapshots extends \WP_UnitTestCase {
*/
function setUp() {
$plugin = get_plugin_instance();
- if ( $plugin->compat ) {
- $this->front_param = 'customize_snapshot_uuid';
- } else {
- $this->front_param = 'changeset_uuid';
- }
+ $this->front_param = 'changeset_uuid';
}
/**
@@ -63,31 +59,16 @@ function test_customize_snapshots_php_version_text() {
$this->assertContains( 'Customize Snapshots plugin error:', customize_snapshots_php_version_text() );
}
- /**
- * Tests is_previewing_settings().
- *
- * @see is_previewing_settings()
- */
- public function test_is_previewing_settings() {
- if ( ! get_plugin_instance()->compat ) {
- $this->markTestIncomplete( 'WordPress Version 4.6.x or below is required for this test-case.' );
- }
- $this->assertFalse( is_previewing_settings() );
- do_action( 'customize_preview_init' );
- $this->assertTrue( is_previewing_settings() );
- }
-
/**
* Tests current_snapshot_uuid().
*
* @see current_snapshot_uuid()
*/
public function test_current_snapshot_uuid() {
- global $customize_snapshots_plugin;
- $uuid = '65aee1ff-af47-47df-9e14-9c69b3017cd3';
- $_REQUEST[ $this->front_param ] = $uuid;
- $customize_snapshots_plugin = new Plugin();
- $customize_snapshots_plugin->init();
- $this->assertEquals( $uuid, current_snapshot_uuid() );
+ global $wp_customize;
+ require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
+ $changeset_uuid = '65aee1ff-af47-47df-9e14-9c69b3017cd3';
+ $wp_customize = new \WP_Customize_Manager( compact( 'changeset_uuid' ) );
+ $this->assertEquals( $changeset_uuid, current_snapshot_uuid() );
}
}