Customize: Introduce drafting and scheduling for Customizer changesets.

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

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

Built from https://develop.svn.wordpress.org/trunk@41626


git-svn-id: http://core.svn.wordpress.org/trunk@41461 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Weston Ruter 2017-09-27 22:25:46 +00:00
parent 0892a6ebbf
commit 8043c2d8e5
14 changed files with 2220 additions and 221 deletions

View File

@ -24,11 +24,94 @@ body {
color: #555d66;
}
#customize-header-actions .button-primary {
#customize-save-button-wrapper {
float: left;
margin-top: 9px;
}
#customize-save-button-wrapper .save {
float: right;
border-radius: 3px;
box-shadow: none; /* @todo Adjust box shadow based on the disable states of paired button. */
display: none; /* Shown when ready. */
margin-top: 0;
}
#customize-save-button-wrapper .save.has-next-sibling {
border-radius: 0 3px 3px 0;
}
#customize-outer-theme-controls-wrapper {
position: absolute;
top: 0;
bottom: 0;
right: -301px;
visibility: hidden;
overflow-x: hidden;
overflow-y: auto;
width: 300px;
margin: 0;
z-index: 4;
background: #eee;
transition: right .18s;
border-left: 1px solid #ddd;
}
.outer-section-open .wp-full-overlay.expanded {
margin-right: 300px;
}
#customize-theme-controls .control-section-outer {
display: none !important;
}
#customize-outer-theme-controls .accordion-section-content {
padding: 12px;
}
#customize-outer-theme-controls .accordion-section-content.open {
display: block;
}
.outer-section-open .wp-full-overlay.expanded #customize-outer-theme-controls-wrapper {
visibility: visible;
right: 0;
transition: right .18s;
}
.customize-outer-pane-parent {
margin: 0;
}
.outer-section-open .wp-full-overlay.expanded #customize-preview {
opacity: 0.4;
}
body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main {
right: 300px;
}
#customize-outer-theme-controls li.notice {
padding-top: 8px;
padding-bottom: 8px;
margin-right: 0;
margin-bottom: 10px;
}
#publish-settings {
text-indent: 0;
border-radius: 3px 0 0 3px;
padding-right: 0;
padding-left: 0;
box-shadow: none; /* @todo Adjust box shadow based on the disable states of paired button. */
font-size: 14px;
width: 30px;
float: right;
display: none; /* Shown when ready. */
-webkit-transform: none;
transform: none;
margin-top: 0;
}
#customize-header-actions .spinner {
margin-top: 13px;
margin-left: 4px;
@ -53,10 +136,181 @@ body {
margin-bottom: 15px;
}
#customize-control-changeset_status label,
#customize-control-changeset_preview_link input {
background-color: #ffffff;
border-bottom: 1px solid #ddd;
box-sizing: content-box;
width: 100%;
margin-right: -12px;
padding-right: 12px;
padding-left: 12px;
}
#customize-controls .date-input:invalid {
border-color: red;
}
.date-time-fields .month-field {
width: 79px;
}
.date-time-fields .day-field,
.date-time-fields .hour-field,
.date-time-fields .minute-field {
width: 46px;
}
.date-time-fields .year-field {
width: 60px;
}
.date-time-fields .am-pm-field {
width: 53px;
}
#customize-control-changeset_status label {
padding-top: 10px;
padding-bottom: 10px;
font-weight: 500;
}
#customize-control-changeset_status label:first-of-type {
border-top: 1px solid #ddd;
}
#customize-control-changeset_status .customize-control-title {
margin-bottom: 6px;
}
#customize-control-changeset_status input {
margin-right: 0;
}
#customize-control-changeset_preview_link {
position: relative;
display: block;
}
.customize-copy-preview-link {
position: absolute;
bottom: 9px;
left: 0;
}
.customize-copy-preview-link:before,
.customize-copy-preview-link:after {
content: '';
height: 28px;
position: absolute;
background: #ffffff;
top: -1px;
}
.customize-copy-preview-link:before {
right: -10px;
width: 9px;
opacity: 0.75;
}
.customize-copy-preview-link:after {
right: -5px;
width: 4px;
opacity: 0.8;
}
#customize-control-changeset_preview_link input {
line-height: 2.5;
border-top: 1px solid #ddd;
border-right: none;
border-left: none;
text-indent: -999px;
color: white;
}
#customize-control-changeset_preview_link label {
position: relative;
display: block;
}
#customize-control-changeset_preview_link a.preview-control-element {
display: inline-block;
position: absolute;
white-space: nowrap;
overflow: hidden;
width: 217px;
bottom: 14px;
font-size: 14px;
text-decoration: none;
}
#customize-control-changeset_preview_link a.preview-control-element.disabled,
#customize-control-changeset_preview_link a.preview-control-element.disabled:active,
#customize-control-changeset_preview_link a.preview-control-element.disabled:focus,
#customize-control-changeset_preview_link a.preview-control-element.disabled:visited {
color: black;
opacity: 0.4;
cursor: default;
outline: none;
box-shadow: none;
}
#sub-accordion-section-publish_settings .customize-section-description-container {
display: none;
}
#customize-controls .customize-info.section-meta {
margin-bottom: 15px;
}
.date-time-fields {
padding-top: 10px;
padding-bottom:10px;
}
.date-time-fields label,
.date-time-fields .date-time-separator {
float: right;
margin-left:5px;
}
.date-time-fields .date-time-separator {
line-height: 2;
}
.date-time-fields .time-row {
padding-top: 12px;
}
.date-time-fields .date-timezone {
float: right;
line-height: 2.2;
text-decoration: none;
}
#customize-control-changeset_preview_link {
margin-top: 20px;
}
#customize-control-changeset_status {
margin-bottom: 0;
padding-bottom: 0;
}
#customize-control-changeset_scheduled_date {
box-sizing: content-box;
width: 100%;
margin-right: -12px;
padding: 12px 12px 18px;
background: #ffffff;
border-bottom: 1px solid #ddd;
margin-bottom: 0;
}
#customize-control-changeset_scheduled_date .customize-control-description {
font-style: normal;
}
#customize-controls .customize-info.is-in-view,
#customize-controls .customize-section-title.is-in-view {
position: absolute;
@ -105,6 +359,8 @@ body {
#customize-controls .customize-pane-child .customize-section-title h3,
#customize-controls .customize-pane-child h3.customize-section-title,
#customize-outer-theme-controls .customize-pane-child .customize-section-title h3,
#customize-outer-theme-controls .customize-pane-child h3.customize-section-title,
#customize-controls .customize-info .panel-title {
font-size: 20px;
font-weight: 200;
@ -150,6 +406,7 @@ body {
#customize-controls .customize-info .customize-panel-description,
#customize-controls .customize-info .customize-section-description,
#customize-outer-theme-controls .customize-info .customize-section-description,
#customize-controls .no-widget-areas-rendered-notice {
color: #555d66;
display: none;
@ -171,7 +428,8 @@ body {
margin-bottom: 0;
}
#customize-controls .customize-info .customize-section-description {
#customize-controls .customize-info .customize-section-description,
#customize-outer-theme-controls .customize-section-description {
margin-bottom: 15px;
}
@ -189,11 +447,13 @@ body {
padding-left: 30px;
}
#customize-theme-controls .control-section {
#customize-theme-controls .control-section,
#customize-outer-theme-controls .control-section {
border: none;
}
#customize-theme-controls .accordion-section-title {
#customize-theme-controls .accordion-section-title,
#customize-outer-theme-controls .accordion-section-title {
color: #555d66;
background-color: #fff;
border-bottom: 1px solid #ddd;
@ -209,12 +469,14 @@ body {
border-right: 4px solid #fff;
}
#customize-theme-controls .accordion-section-title:after {
#customize-theme-controls .accordion-section-title:after,
#customize-outer-theme-controls .accordion-section-title:after {
content: "\f341";
color: #a0a5aa;
}
#customize-theme-controls .accordion-section-content {
#customize-theme-controls .accordion-section-content,
#customize-outer-theme-controls .accordion-section-content {
color: #555d66;
background: transparent;
}
@ -222,6 +484,9 @@ body {
#customize-controls .control-section:hover > .accordion-section-title,
#customize-controls .control-section .accordion-section-title:hover,
#customize-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section .accordion-section-title:hover,
#customize-outer-theme-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section .accordion-section-title:focus,
#customize-controls .control-section .accordion-section-title:focus {
color: #0073aa;
background: #f3f3f5;
@ -242,7 +507,11 @@ body {
#customize-theme-controls .control-section:hover > .accordion-section-title:after,
#customize-theme-controls .control-section .accordion-section-title:hover:after,
#customize-theme-controls .control-section.open .accordion-section-title:after,
#customize-theme-controls .control-section .accordion-section-title:focus:after {
#customize-theme-controls .control-section .accordion-section-title:focus:after,
#customize-outer-theme-controls .control-section:hover > .accordion-section-title:after,
#customize-outer-theme-controls .control-section .accordion-section-title:hover:after,
#customize-outer-theme-controls .control-section.open .accordion-section-title:after,
#customize-outer-theme-controls .control-section .accordion-section-title:focus:after {
color: #0073aa;
}
@ -250,7 +519,8 @@ body {
border-bottom: 1px solid #eee;
}
#customize-theme-controls .control-section.open .accordion-section-title {
#customize-theme-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section.open .accordion-section-title {
border-bottom-color: #eee !important;
}
@ -828,6 +1098,10 @@ p.customize-section-description {
margin: 0;
}
.wp-full-overlay.collapsed #customize-controls #customize-notifications-area {
display: none !important;
}
#customize-controls #customize-notifications-area,
#customize-controls .customize-section-title > .customize-control-notifications-container,
#customize-controls .panel-meta > .customize-control-notifications-container {
@ -1119,18 +1393,60 @@ p.customize-section-description {
animation: dice-color-change 3s infinite;
}
@-webkit-keyframes dice-color-change {
0% { color: #d4b146; }
50% { color: #ef54b0; }
75% { color: #7190d3; }
100% { color: #d4b146; }
.button-see-me {
-webkit-animation: bounce .7s 1;
animation: bounce .7s 1;
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
@keyframes dice-color-change {
0% { color: #d4b146; }
50% { color: #ef54b0; }
75% { color: #7190d3; }
100% { color: #d4b146; }
@-webkit-keyframes bounce {
from, 20%, 53%, 80%, to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-webkit-transform: translate3d(0,0,0);
}
40%, 43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -12px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -6px, 0);
}
90% {
-webkit-transform: translate3d(0,-1px,0);
}
}
@keyframes bounce {
from, 20%, 53%, 80%, to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
40%, 43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -12px, 0);
transform: translate3d(0, -12px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -6px, 0);
transform: translate3d(0, -6px, 0);
}
90% {
-webkit-transform: translate3d(0,-1px,0);
transform: translate3d(0,-1px,0);
}
}
.customize-control-header .choice {
@ -1310,7 +1626,8 @@ p.customize-section-description {
}
#customize-controls .control-section-themes .accordion-section-title span.customize-action,
#customize-controls .customize-section-title span.customize-action {
#customize-controls .customize-section-title span.customize-action,
#customize-outer-theme-controls .customize-section-title span.customize-action {
font-size: 13px;
display: block;
font-weight: 400;
@ -1843,6 +2160,27 @@ body.adding-widget .add-new-widget:before,
line-height: 32px;
}
.customize-control .date-time-fields select {
height: 39px;
}
.date-time-fields .month-field {
width: 79px;
}
.date-time-fields .day-field,
.date-time-fields .hour-field,
.date-time-fields .minute-field {
width: 55px;
}
.date-time-fields .year-field {
width: 80px;
}
.date-time-fields .date-timezone {
line-height: 3.2;
}
.wp-core-ui.wp-customizer .button {
margin-top: 12px;
}
@ -1853,7 +2191,8 @@ body.adding-widget .add-new-widget:before,
width: 100%;
}
.wp-full-overlay.expanded {
.wp-full-overlay.expanded,
.outer-section-open .wp-full-overlay.expanded {
margin-right: 0;
}
@ -1931,12 +2270,17 @@ body.adding-widget .add-new-widget:before,
margin-top: 12px;
}
#customize-header-actions .button-primary {
margin-top: 6px;
#publish-settings {
height: 31px;
}
#customize-control-changeset_status label {
padding-top: 15px;
}
body.adding-widget div#available-widgets,
body.adding-menu-items div#available-menu-items {
body.adding-menu-items div#available-menu-items,
body.outer-section-open div#customize-outer-theme-controls-wrapper {
top: 46px;
right: 0;
z-index: 10;

File diff suppressed because one or more lines are too long

View File

@ -24,11 +24,94 @@ body {
color: #555d66;
}
#customize-header-actions .button-primary {
#customize-save-button-wrapper {
float: right;
margin-top: 9px;
}
#customize-save-button-wrapper .save {
float: left;
border-radius: 3px;
box-shadow: none; /* @todo Adjust box shadow based on the disable states of paired button. */
display: none; /* Shown when ready. */
margin-top: 0;
}
#customize-save-button-wrapper .save.has-next-sibling {
border-radius: 3px 0 0 3px;
}
#customize-outer-theme-controls-wrapper {
position: absolute;
top: 0;
bottom: 0;
left: -301px;
visibility: hidden;
overflow-x: hidden;
overflow-y: auto;
width: 300px;
margin: 0;
z-index: 4;
background: #eee;
transition: left .18s;
border-right: 1px solid #ddd;
}
.outer-section-open .wp-full-overlay.expanded {
margin-left: 300px;
}
#customize-theme-controls .control-section-outer {
display: none !important;
}
#customize-outer-theme-controls .accordion-section-content {
padding: 12px;
}
#customize-outer-theme-controls .accordion-section-content.open {
display: block;
}
.outer-section-open .wp-full-overlay.expanded #customize-outer-theme-controls-wrapper {
visibility: visible;
left: 0;
transition: left .18s;
}
.customize-outer-pane-parent {
margin: 0;
}
.outer-section-open .wp-full-overlay.expanded #customize-preview {
opacity: 0.4;
}
body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main {
left: 300px;
}
#customize-outer-theme-controls li.notice {
padding-top: 8px;
padding-bottom: 8px;
margin-left: 0;
margin-bottom: 10px;
}
#publish-settings {
text-indent: 0;
border-radius: 0 3px 3px 0;
padding-left: 0;
padding-right: 0;
box-shadow: none; /* @todo Adjust box shadow based on the disable states of paired button. */
font-size: 14px;
width: 30px;
float: left;
display: none; /* Shown when ready. */
-webkit-transform: none;
transform: none;
margin-top: 0;
}
#customize-header-actions .spinner {
margin-top: 13px;
margin-right: 4px;
@ -53,10 +136,181 @@ body {
margin-bottom: 15px;
}
#customize-control-changeset_status label,
#customize-control-changeset_preview_link input {
background-color: #ffffff;
border-bottom: 1px solid #ddd;
box-sizing: content-box;
width: 100%;
margin-left: -12px;
padding-left: 12px;
padding-right: 12px;
}
#customize-controls .date-input:invalid {
border-color: red;
}
.date-time-fields .month-field {
width: 79px;
}
.date-time-fields .day-field,
.date-time-fields .hour-field,
.date-time-fields .minute-field {
width: 46px;
}
.date-time-fields .year-field {
width: 60px;
}
.date-time-fields .am-pm-field {
width: 53px;
}
#customize-control-changeset_status label {
padding-top: 10px;
padding-bottom: 10px;
font-weight: 500;
}
#customize-control-changeset_status label:first-of-type {
border-top: 1px solid #ddd;
}
#customize-control-changeset_status .customize-control-title {
margin-bottom: 6px;
}
#customize-control-changeset_status input {
margin-left: 0;
}
#customize-control-changeset_preview_link {
position: relative;
display: block;
}
.customize-copy-preview-link {
position: absolute;
bottom: 9px;
right: 0;
}
.customize-copy-preview-link:before,
.customize-copy-preview-link:after {
content: '';
height: 28px;
position: absolute;
background: #ffffff;
top: -1px;
}
.customize-copy-preview-link:before {
left: -10px;
width: 9px;
opacity: 0.75;
}
.customize-copy-preview-link:after {
left: -5px;
width: 4px;
opacity: 0.8;
}
#customize-control-changeset_preview_link input {
line-height: 2.5;
border-top: 1px solid #ddd;
border-left: none;
border-right: none;
text-indent: -999px;
color: white;
}
#customize-control-changeset_preview_link label {
position: relative;
display: block;
}
#customize-control-changeset_preview_link a.preview-control-element {
display: inline-block;
position: absolute;
white-space: nowrap;
overflow: hidden;
width: 217px;
bottom: 14px;
font-size: 14px;
text-decoration: none;
}
#customize-control-changeset_preview_link a.preview-control-element.disabled,
#customize-control-changeset_preview_link a.preview-control-element.disabled:active,
#customize-control-changeset_preview_link a.preview-control-element.disabled:focus,
#customize-control-changeset_preview_link a.preview-control-element.disabled:visited {
color: black;
opacity: 0.4;
cursor: default;
outline: none;
box-shadow: none;
}
#sub-accordion-section-publish_settings .customize-section-description-container {
display: none;
}
#customize-controls .customize-info.section-meta {
margin-bottom: 15px;
}
.date-time-fields {
padding-top: 10px;
padding-bottom:10px;
}
.date-time-fields label,
.date-time-fields .date-time-separator {
float: left;
margin-right:5px;
}
.date-time-fields .date-time-separator {
line-height: 2;
}
.date-time-fields .time-row {
padding-top: 12px;
}
.date-time-fields .date-timezone {
float: left;
line-height: 2.2;
text-decoration: none;
}
#customize-control-changeset_preview_link {
margin-top: 20px;
}
#customize-control-changeset_status {
margin-bottom: 0;
padding-bottom: 0;
}
#customize-control-changeset_scheduled_date {
box-sizing: content-box;
width: 100%;
margin-left: -12px;
padding: 12px 12px 18px;
background: #ffffff;
border-bottom: 1px solid #ddd;
margin-bottom: 0;
}
#customize-control-changeset_scheduled_date .customize-control-description {
font-style: normal;
}
#customize-controls .customize-info.is-in-view,
#customize-controls .customize-section-title.is-in-view {
position: absolute;
@ -105,6 +359,8 @@ body {
#customize-controls .customize-pane-child .customize-section-title h3,
#customize-controls .customize-pane-child h3.customize-section-title,
#customize-outer-theme-controls .customize-pane-child .customize-section-title h3,
#customize-outer-theme-controls .customize-pane-child h3.customize-section-title,
#customize-controls .customize-info .panel-title {
font-size: 20px;
font-weight: 200;
@ -150,6 +406,7 @@ body {
#customize-controls .customize-info .customize-panel-description,
#customize-controls .customize-info .customize-section-description,
#customize-outer-theme-controls .customize-info .customize-section-description,
#customize-controls .no-widget-areas-rendered-notice {
color: #555d66;
display: none;
@ -171,7 +428,8 @@ body {
margin-bottom: 0;
}
#customize-controls .customize-info .customize-section-description {
#customize-controls .customize-info .customize-section-description,
#customize-outer-theme-controls .customize-section-description {
margin-bottom: 15px;
}
@ -189,11 +447,13 @@ body {
padding-right: 30px;
}
#customize-theme-controls .control-section {
#customize-theme-controls .control-section,
#customize-outer-theme-controls .control-section {
border: none;
}
#customize-theme-controls .accordion-section-title {
#customize-theme-controls .accordion-section-title,
#customize-outer-theme-controls .accordion-section-title {
color: #555d66;
background-color: #fff;
border-bottom: 1px solid #ddd;
@ -209,12 +469,14 @@ body {
border-left: 4px solid #fff;
}
#customize-theme-controls .accordion-section-title:after {
#customize-theme-controls .accordion-section-title:after,
#customize-outer-theme-controls .accordion-section-title:after {
content: "\f345";
color: #a0a5aa;
}
#customize-theme-controls .accordion-section-content {
#customize-theme-controls .accordion-section-content,
#customize-outer-theme-controls .accordion-section-content {
color: #555d66;
background: transparent;
}
@ -222,6 +484,9 @@ body {
#customize-controls .control-section:hover > .accordion-section-title,
#customize-controls .control-section .accordion-section-title:hover,
#customize-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section .accordion-section-title:hover,
#customize-outer-theme-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section .accordion-section-title:focus,
#customize-controls .control-section .accordion-section-title:focus {
color: #0073aa;
background: #f3f3f5;
@ -242,7 +507,11 @@ body {
#customize-theme-controls .control-section:hover > .accordion-section-title:after,
#customize-theme-controls .control-section .accordion-section-title:hover:after,
#customize-theme-controls .control-section.open .accordion-section-title:after,
#customize-theme-controls .control-section .accordion-section-title:focus:after {
#customize-theme-controls .control-section .accordion-section-title:focus:after,
#customize-outer-theme-controls .control-section:hover > .accordion-section-title:after,
#customize-outer-theme-controls .control-section .accordion-section-title:hover:after,
#customize-outer-theme-controls .control-section.open .accordion-section-title:after,
#customize-outer-theme-controls .control-section .accordion-section-title:focus:after {
color: #0073aa;
}
@ -250,7 +519,8 @@ body {
border-bottom: 1px solid #eee;
}
#customize-theme-controls .control-section.open .accordion-section-title {
#customize-theme-controls .control-section.open .accordion-section-title,
#customize-outer-theme-controls .control-section.open .accordion-section-title {
border-bottom-color: #eee !important;
}
@ -828,6 +1098,10 @@ p.customize-section-description {
margin: 0;
}
.wp-full-overlay.collapsed #customize-controls #customize-notifications-area {
display: none !important;
}
#customize-controls #customize-notifications-area,
#customize-controls .customize-section-title > .customize-control-notifications-container,
#customize-controls .panel-meta > .customize-control-notifications-container {
@ -1119,18 +1393,60 @@ p.customize-section-description {
animation: dice-color-change 3s infinite;
}
@-webkit-keyframes dice-color-change {
0% { color: #d4b146; }
50% { color: #ef54b0; }
75% { color: #7190d3; }
100% { color: #d4b146; }
.button-see-me {
-webkit-animation: bounce .7s 1;
animation: bounce .7s 1;
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
@keyframes dice-color-change {
0% { color: #d4b146; }
50% { color: #ef54b0; }
75% { color: #7190d3; }
100% { color: #d4b146; }
@-webkit-keyframes bounce {
from, 20%, 53%, 80%, to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-webkit-transform: translate3d(0,0,0);
}
40%, 43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -12px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -6px, 0);
}
90% {
-webkit-transform: translate3d(0,-1px,0);
}
}
@keyframes bounce {
from, 20%, 53%, 80%, to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
40%, 43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -12px, 0);
transform: translate3d(0, -12px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -6px, 0);
transform: translate3d(0, -6px, 0);
}
90% {
-webkit-transform: translate3d(0,-1px,0);
transform: translate3d(0,-1px,0);
}
}
.customize-control-header .choice {
@ -1310,7 +1626,8 @@ p.customize-section-description {
}
#customize-controls .control-section-themes .accordion-section-title span.customize-action,
#customize-controls .customize-section-title span.customize-action {
#customize-controls .customize-section-title span.customize-action,
#customize-outer-theme-controls .customize-section-title span.customize-action {
font-size: 13px;
display: block;
font-weight: 400;
@ -1843,6 +2160,27 @@ body.adding-widget .add-new-widget:before,
line-height: 32px;
}
.customize-control .date-time-fields select {
height: 39px;
}
.date-time-fields .month-field {
width: 79px;
}
.date-time-fields .day-field,
.date-time-fields .hour-field,
.date-time-fields .minute-field {
width: 55px;
}
.date-time-fields .year-field {
width: 80px;
}
.date-time-fields .date-timezone {
line-height: 3.2;
}
.wp-core-ui.wp-customizer .button {
margin-top: 12px;
}
@ -1853,7 +2191,8 @@ body.adding-widget .add-new-widget:before,
width: 100%;
}
.wp-full-overlay.expanded {
.wp-full-overlay.expanded,
.outer-section-open .wp-full-overlay.expanded {
margin-left: 0;
}
@ -1931,12 +2270,17 @@ body.adding-widget .add-new-widget:before,
margin-top: 12px;
}
#customize-header-actions .button-primary {
margin-top: 6px;
#publish-settings {
height: 31px;
}
#customize-control-changeset_status label {
padding-top: 15px;
}
body.adding-widget div#available-widgets,
body.adding-menu-items div#available-menu-items {
body.adding-menu-items div#available-menu-items,
body.outer-section-open div#customize-outer-theme-controls-wrapper {
top: 46px;
left: 0;
z-index: 10;

File diff suppressed because one or more lines are too long

View File

@ -27,14 +27,30 @@ if ( ! current_user_can( 'customize' ) ) {
global $wp_scripts, $wp_customize;
if ( $wp_customize->changeset_post_id() ) {
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->edit_post, $wp_customize->changeset_post_id() ) ) {
$changeset_post = get_post( $wp_customize->changeset_post_id() );
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->edit_post, $changeset_post->ID ) ) {
wp_die(
'<h1>' . __( 'Cheatin&#8217; uh?' ) . '</h1>' .
'<p>' . __( 'Sorry, you are not allowed to edit this changeset.' ) . '</p>',
403
);
}
if ( in_array( get_post_status( $wp_customize->changeset_post_id() ), array( 'publish', 'trash' ), true ) ) {
$missed_schedule = (
'future' === $changeset_post->post_status &&
get_post_time( 'G', true, $changeset_post ) < time()
);
if ( $missed_schedule ) {
wp_publish_post( $changeset_post->ID );
wp_die(
'<h1>' . __( 'Your scheduled changes just published' ) . '</h1>' .
'<p><a href="' . esc_url( remove_query_arg( 'changeset_uuid' ) ) . '">' . __( 'Customize New Changes' ) . '</a></p>',
200
);
}
if ( in_array( get_post_status( $changeset_post->ID ), array( 'publish', 'trash' ), true ) ) {
wp_die(
'<h1>' . __( 'Cheatin&#8217; uh?' ) . '</h1>' .
'<p>' . __( 'This changeset has already been published and cannot be further modified.' ) . '</p>' .
@ -132,14 +148,11 @@ do_action( 'customize_controls_print_scripts' );
<div class="wp-full-overlay expanded">
<form id="customize-controls" class="wrap wp-full-overlay-sidebar">
<div id="customize-header-actions" class="wp-full-overlay-header">
<?php
$save_text = $wp_customize->is_theme_active() ? __( 'Save &amp; Publish' ) : __( 'Save &amp; Activate' );
$save_attrs = array();
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
$save_attrs['style'] = 'display: none';
}
submit_button( $save_text, 'primary save', 'save', false, $save_attrs );
?>
<?php $save_text = $wp_customize->is_theme_active() ? __( 'Publish' ) : __( 'Activate &amp; Publish' ); ?>
<div id="customize-save-button-wrapper" class="customize-save-button-wrapper" >
<?php submit_button( $save_text, 'primary save', 'save', false ); ?>
<button id="publish-settings" class="publish-settings button-primary button dashicons dashicons-admin-generic" aria-label="<?php esc_attr_e( 'Publish Settings' ); ?>" aria-expanded="false" disabled></button>
</div>
<span class="spinner"></span>
<button type="button" class="customize-controls-preview-toggle">
<span class="controls"><?php _e( 'Customize' ); ?></span>
@ -203,6 +216,13 @@ do_action( 'customize_controls_print_scripts' );
</div>
</form>
<div id="customize-preview" class="wp-full-overlay-main"></div>
<div id="customize-sidebar-outer-content">
<div id="customize-outer-theme-controls-wrapper">
<div id="customize-outer-theme-controls">
<ul class="customize-outer-pane-parent"><?php // Outer panel and sections are not implemented, but its here as a placeholder to avoid any side-effect in api.Section. ?></ul>
</div>
</div>
</div>
<?php
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -747,3 +747,8 @@ require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add
* WP_Customize_New_Menu_Control class.
*/
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' );
/**
* WP_Customize_Date_Time_Control class.
*/
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-date-time-control.php' );

View File

@ -596,38 +596,10 @@ final class WP_Customize_Manager {
* @since 4.9.0
*/
public function establish_loaded_changeset() {
/**
* Filters whether or not changeset branching is allowed.
*
* By default in core, when changeset branching is not allowed, changesets will operate
* linearly in that only one saved changeset will exist at a time (with a 'draft' or
* 'future' status). This makes the Customizer operate in a way that is similar to going to
* "edit" to one existing post: all users will be making changes to the same post, and autosave
* revisions will be made for that post.
*
* By contrast, when changeset branching is allowed, then the model is like users going
* to "add new" for a page and each user makes changes independently of each other since
* they are all operating on their own separate pages, each getting their own separate
* initial auto-drafts and then once initially saved, autosave revisions on top of that
* user's specific post.
*
* Since linear changesets are deemed to be more suitable for the majority of WordPress users,
* they are the default. For WordPress sites that have heavy site management in the Customizer
* by multiple users then branching changesets should be enabled by means of this filter.
*
* @since 4.9.0
*
* @param bool $allow_branching Whether branching is allowed. If `false`, the default,
* then only one saved changeset exists at a time.
* @param WP_Customize_Manager $wp_customize Manager instance.
*/
$this->branching = apply_filters( 'customize_changeset_branching', $this->branching, $this );
if ( empty( $this->_changeset_uuid ) ) {
$changeset_uuid = null;
if ( ! $this->branching ) {
if ( ! $this->branching() ) {
$unpublished_changeset_posts = $this->get_changeset_posts( array(
'post_status' => array_diff( get_post_stati(), array( 'auto-draft', 'publish', 'trash', 'inherit', 'private' ) ),
'exclude_restore_dismissed' => false,
@ -751,6 +723,58 @@ final class WP_Customize_Manager {
return $this->settings_previewed;
}
/**
* Gets whether data from a changeset's autosaved revision should be loaded if it exists.
*
* @since 4.9.0
* @see WP_Customize_Manager::changeset_data()
*
* @return bool Is using autosaved changeset revision.
*/
public function autosaved() {
return $this->autosaved;
}
/**
* Whether the changeset branching is allowed.
*
* @since 4.9.0
* @see WP_Customize_Manager::establish_loaded_changeset()
*
* @return bool Is changeset branching.
*/
public function branching() {
/**
* Filters whether or not changeset branching is allowed.
*
* By default in core, when changeset branching is not allowed, changesets will operate
* linearly in that only one saved changeset will exist at a time (with a 'draft' or
* 'future' status). This makes the Customizer operate in a way that is similar to going to
* "edit" to one existing post: all users will be making changes to the same post, and autosave
* revisions will be made for that post.
*
* By contrast, when changeset branching is allowed, then the model is like users going
* to "add new" for a page and each user makes changes independently of each other since
* they are all operating on their own separate pages, each getting their own separate
* initial auto-drafts and then once initially saved, autosave revisions on top of that
* user's specific post.
*
* Since linear changesets are deemed to be more suitable for the majority of WordPress users,
* they are the default. For WordPress sites that have heavy site management in the Customizer
* by multiple users then branching changesets should be enabled by means of this filter.
*
* @since 4.9.0
*
* @param bool $allow_branching Whether branching is allowed. If `false`, the default,
* then only one saved changeset exists at a time.
* @param WP_Customize_Manager $wp_customize Manager instance.
*/
$this->branching = apply_filters( 'customize_changeset_branching', $this->branching, $this );
return $this->branching;
}
/**
* Get the changeset UUID.
*
@ -763,7 +787,7 @@ final class WP_Customize_Manager {
*/
public function changeset_uuid() {
if ( empty( $this->_changeset_uuid ) ) {
throw new Exception( 'Changeset UUID has not been set.' ); // @todo Replace this with a call to `WP_Customize_Manager::establish_loaded_changeset()` during 4.9-beta2.
$this->establish_loaded_changeset();
}
return $this->_changeset_uuid;
}
@ -980,6 +1004,30 @@ final class WP_Customize_Manager {
return get_posts( $args );
}
/**
* Dismiss all of the current user's auto-drafts (other than the present one).
*
* @since 4.9.0
* @return int The number of auto-drafts that were dismissed.
*/
protected function dismiss_user_auto_draft_changesets() {
$changeset_autodraft_posts = $this->get_changeset_posts( array(
'post_status' => 'auto-draft',
'exclude_restore_dismissed' => true,
'posts_per_page' => -1,
) );
$dismissed = 0;
foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
if ( $autosave_autodraft_post->ID === $this->changeset_post_id() ) {
continue;
}
if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) {
$dismissed++;
}
}
return $dismissed;
}
/**
* Get the changeset post id for the loaded changeset.
*
@ -1050,7 +1098,7 @@ final class WP_Customize_Manager {
if ( ! $changeset_post_id ) {
$this->_changeset_data = array();
} else {
if ( $this->autosaved ) {
if ( $this->autosaved() ) {
$autosave_post = wp_get_post_autosave( $changeset_post_id );
if ( $autosave_post ) {
$data = $this->get_changeset_post_data( $autosave_post->ID );
@ -1972,7 +2020,7 @@ final class WP_Customize_Manager {
$settings = array(
'changeset' => array(
'uuid' => $this->changeset_uuid(),
'autosaved' => $this->autosaved,
'autosaved' => $this->autosaved(),
),
'timeouts' => array(
'selectiveRefresh' => 250,
@ -2345,28 +2393,24 @@ final class WP_Customize_Manager {
}
} else {
$response = $r;
$changeset_post = get_post( $this->changeset_post_id() );
// Dismiss all other auto-draft changeset posts for this user (they serve like autosave revisions), as there should only be one.
if ( $is_new_changeset ) {
$changeset_autodraft_posts = $this->get_changeset_posts( array(
'post_status' => 'auto-draft',
'exclude_restore_dismissed' => true,
'posts_per_page' => -1,
) );
foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
if ( $autosave_autodraft_post->ID !== $this->changeset_post_id() ) {
update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true );
}
}
$this->dismiss_user_auto_draft_changesets();
}
// Note that if the changeset status was publish, then it will get set to trash if revisions are not supported.
$response['changeset_status'] = get_post_status( $this->changeset_post_id() );
$response['changeset_status'] = $changeset_post->post_status;
if ( $is_publish && 'trash' === $response['changeset_status'] ) {
$response['changeset_status'] = 'publish';
}
if ( 'publish' === $response['changeset_status'] ) {
if ( 'future' === $response['changeset_status'] ) {
$response['changeset_date'] = $changeset_post->post_date;
}
if ( 'publish' === $response['changeset_status'] || 'trash' === $response['changeset_status'] ) {
$response['next_changeset_uuid'] = wp_generate_uuid4();
}
}
@ -2434,7 +2478,13 @@ final class WP_Customize_Manager {
if ( $changeset_post_id ) {
$existing_status = get_post_status( $changeset_post_id );
if ( 'publish' === $existing_status || 'trash' === $existing_status ) {
return new WP_Error( 'changeset_already_published' );
return new WP_Error(
'changeset_already_published',
__( 'The previous set of changes already been published. Please try saving your current set of changes again.' ),
array(
'next_changeset_uuid' => wp_generate_uuid4(),
)
);
}
$existing_changeset_data = $this->get_changeset_post_data( $changeset_post_id );
@ -2453,7 +2503,7 @@ final class WP_Customize_Manager {
if ( $args['date_gmt'] ) {
$is_future_dated = ( mysql2date( 'U', $args['date_gmt'], false ) > mysql2date( 'U', $now, false ) );
if ( ! $is_future_dated ) {
return new WP_Error( 'not_future_date' ); // Only future dates are allowed.
return new WP_Error( 'not_future_date', __( 'You must supply a future date to schedule.' ) ); // Only future dates are allowed.
}
if ( ! $this->is_theme_active() && ( 'future' === $args['status'] || $is_future_dated ) ) {
@ -2468,7 +2518,7 @@ final class WP_Customize_Manager {
// Fail if the new status is future but the existing post's date is not in the future.
$changeset_post = get_post( $changeset_post_id );
if ( mysql2date( 'U', $changeset_post->post_date_gmt, false ) <= mysql2date( 'U', $now, false ) ) {
return new WP_Error( 'not_future_date' );
return new WP_Error( 'not_future_date', __( 'You must supply a future date to schedule.' ) );
}
}
@ -3056,24 +3106,11 @@ final class WP_Customize_Manager {
$changeset_post_id = $this->changeset_post_id();
if ( empty( $changeset_post_id ) || 'auto-draft' === get_post_status( $changeset_post_id ) ) {
$changeset_autodraft_posts = $this->get_changeset_posts( array(
'post_status' => 'auto-draft',
'exclude_restore_dismissed' => true,
'posts_per_page' => -1,
) );
$dismissed = 0;
foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) {
if ( $autosave_autodraft_post->ID === $changeset_post_id ) {
continue;
}
if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) {
$dismissed++;
}
}
$dismissed = $this->dismiss_user_auto_draft_changesets();
if ( $dismissed > 0 ) {
wp_send_json_success( 'auto_draft_dismissed' );
} else {
wp_send_json_error( 'no_autosave_to_delete', 404 );
wp_send_json_error( 'no_auto_draft_to_delete', 404 );
}
} else {
$revision = wp_get_post_autosave( $changeset_post_id );
@ -3089,7 +3126,7 @@ final class WP_Customize_Manager {
wp_send_json_success( 'autosave_revision_deleted' );
}
} else {
wp_send_json_error( 'no_autosave_to_delete', 404 );
wp_send_json_error( 'no_autosave_revision_to_delete', 404 );
}
}
wp_send_json_error( 'unknown_error', 500 );
@ -3516,6 +3553,21 @@ final class WP_Customize_Manager {
<# } ); #>
</ul>
</script>
<script type="text/html" id="tmpl-customize-preview-link-control" >
<span class="customize-control-title">
<label><?php esc_html_e( 'Share Preview Link' ); ?></label>
</span>
<span class="description customize-control-description"><?php esc_html_e( 'See how changes would look live on your website, and share the preview with people who can\'t access the Customizer.' ); ?></span>
<div class="customize-control-notifications-container"></div>
<div class="preview-link-wrapper">
<label>
<span class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></span>
<a class="preview-control-element" data-component="link" href="" target=""></a>
<input readonly class="preview-control-element" data-component="input" value="test" >
<button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button>
</label>
</div>
</script>
<?php
}
@ -3877,7 +3929,7 @@ final class WP_Customize_Manager {
$autosave_revision_post = null;
$autosave_autodraft_post = null;
$changeset_post_id = $this->changeset_post_id();
if ( ! $this->saved_starter_content_changeset && ! $this->autosaved ) {
if ( ! $this->saved_starter_content_changeset && ! $this->autosaved() ) {
if ( $changeset_post_id ) {
$autosave_revision_post = wp_get_post_autosave( $changeset_post_id );
} else {
@ -3893,15 +3945,25 @@ final class WP_Customize_Manager {
}
// Prepare Customizer settings to pass to JavaScript.
$changeset_post = null;
if ( $changeset_post_id ) {
$changeset_post = get_post( $changeset_post_id );
}
$settings = array(
'changeset' => array(
'uuid' => $this->changeset_uuid(),
'branching' => $this->branching,
'autosaved' => $this->autosaved,
'branching' => $this->branching(),
'autosaved' => $this->autosaved(),
'hasAutosaveRevision' => ! empty( $autosave_revision_post ),
'latestAutoDraftUuid' => $autosave_autodraft_post ? $autosave_autodraft_post->post_name : null,
'status' => $changeset_post_id ? get_post_status( $changeset_post_id ) : '',
'status' => $changeset_post ? $changeset_post->post_status : '',
'currentUserCanPublish' => current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ),
'publishDate' => $changeset_post ? $changeset_post->post_date : '', // @todo Only if future status? Rename to just date?
),
'initialServerDate' => current_time( 'mysql', false ),
'initialServerTimestamp' => floor( microtime( true ) * 1000 ),
'initialClientTimestamp' => -1, // To be set with JS below.
'timeouts' => array(
'windowRefresh' => 250,
'changesetAutoSave' => AUTOSAVE_INTERVAL * 1000,
@ -3957,6 +4019,7 @@ final class WP_Customize_Manager {
?>
<script type="text/javascript">
var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
_wpCustomizeSettings.initialClientTimestamp = _.now();
_wpCustomizeSettings.controls = {};
_wpCustomizeSettings.settings = {};
<?php
@ -4047,6 +4110,54 @@ final class WP_Customize_Manager {
$this->register_control_type( 'WP_Customize_Site_Icon_Control' );
$this->register_control_type( 'WP_Customize_Theme_Control' );
$this->register_control_type( 'WP_Customize_Code_Editor_Control' );
$this->register_control_type( 'WP_Customize_Date_Time_Control' );
/* Publish Settings */
$this->add_section( 'publish_settings', array(
'title' => __( 'Publish Settings' ),
'priority' => 0,
'capability' => 'customize',
'type' => 'outer',
'active_callback' => array( $this, 'is_theme_active' ),
) );
/* Publish Settings Controls */
$status_choices = array(
'publish' => __( 'Publish' ),
'draft' => __( 'Save Draft' ),
'future' => __( 'Schedule' ),
);
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
unset( $status_choices['publish'] );
}
$this->add_control( 'changeset_status', array(
'section' => 'publish_settings',
'settings' => array(),
'type' => 'radio',
'label' => __( 'Action' ),
'choices' => $status_choices,
'capability' => 'customize',
) );
if ( $this->changeset_post_id() && 'future' === get_post_status( $this->changeset_post_id() ) ) {
$initial_date = get_the_time( 'Y-m-d H:i:s', $this->changeset_post_id() );
} else {
$initial_date = current_time( 'mysql', false );
}
$this->add_control( new WP_Customize_Date_Time_Control( $this, 'changeset_scheduled_date', array(
'section' => 'publish_settings',
'settings' => array(),
'type' => 'date_time',
'min_year' => date( 'Y' ),
'allow_past_date' => false,
'twelve_hour_format' => false !== stripos( get_option( 'time_format' ), 'a' ),
'description' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ),
'capability' => 'customize',
'default_value' => $initial_date,
) ) );
/* Themes */

View File

@ -0,0 +1,257 @@
<?php
/**
* Customize API: WP_Customize_Date_Time_Control class
*
* @package WordPress
* @subpackage Customize
* @since 4.9.0
*/
/**
* Customize Date Time Control class.
*
* @since 4.9.0
*
* @see WP_Customize_Control
*/
class WP_Customize_Date_Time_Control extends WP_Customize_Control {
/**
* Customize control type.
*
* @since 4.9.0
* @var string
*/
public $type = 'date_time';
/**
* Minimum Year.
*
* @since 4.9.0
* @var integer
*/
public $min_year = 1000;
/**
* Maximum Year.
*
* @since 4.9.0
* @var integer
*/
public $max_year = 9999;
/**
* Allow past date, if set to false user can only select future date.
*
* @since 4.9.0
* @var boolean
*/
public $allow_past_date = true;
/**
* If set to false the control will appear in 24 hour format,
* the value will still be saved in Y-m-d H:i:s format.
*
* @since 4.9.0
* @var boolean
*/
public $twelve_hour_format = true;
/**
* Default date/time to be displayed in the control.
*
* @since 4.9.0
* @var string
*/
public $default_value;
/**
* Don't render the control's content - it's rendered with a JS template.
*
* @since 4.9.0
*/
public function render_content() {}
/**
* Export data to JS.
*
* @since 4.9.0
* @return array
*/
public function json() {
$data = parent::json();
$data['maxYear'] = intval( $this->max_year );
$data['minYear'] = intval( $this->min_year );
$data['allowPastDate'] = $this->allow_past_date ? true : false;
$data['twelveHourFormat'] = $this->twelve_hour_format ? true : false;
$data['defaultValue'] = $this->default_value;
return $data;
}
/**
* Renders a JS template for the content of date time control.
*
* @since 4.9.0
*/
public function content_template() {
$data = array_merge( $this->json(), $this->get_month_choices() );
$timezone_info = $this->get_timezone_info();
?>
<# _.defaults( data, <?php echo wp_json_encode( $data ); ?> ); #>
<span class="customize-control-title">
<label>{{ data.label }}</label>
</span>
<div class="customize-control-notifications-container"></div>
<span class="description customize-control-description">{{ data.description }}</span>
<div class="date-time-fields">
<div class="day-row">
<span class="title-day"><?php esc_html_e( 'Day' ); ?></span>
<div class="day-fields clear">
<label class="month-field">
<span class="screen-reader-text"><?php esc_html_e( 'Month' ); ?></span>
<select class="date-input month" data-component="month">
<# _.each( data.month_choices, function( choice ) {
if ( _.isObject( choice ) && ! _.isUndefined( choice.text ) && ! _.isUndefined( choice.value ) ) {
text = choice.text;
value = choice.value;
}
#>
<option value="{{ value }}" >
{{ text }}
</option>
<# } ); #>
</select>
</label>
<label class="day-field">
<span class="screen-reader-text"><?php esc_html_e( 'Day' ); ?></span>
<input type="number" size="2" maxlength="2" autocomplete="off" class="date-input day" data-component="day" min="1" max="31"" />
</label>
<span class="time-special-char date-time-separator">,</span>
<label class="year-field">
<span class="screen-reader-text"><?php esc_html_e( 'Year' ); ?></span>
<# var maxYearLength = String( data.maxYear ).length; #>
<input type="number" size="4" maxlength="{{ maxYearLength }}" autocomplete="off" class="date-input year" data-component="year" min="{{ data.minYear }}" max="{{ data.maxYear }}" />
</label>
</div>
</div>
<div class="time-row clear">
<span class="title-time"><?php esc_html_e( 'Time' ); ?></span>
<div class="time-fields clear">
<label class="hour-field">
<span class="screen-reader-text"><?php esc_html_e( 'Hour' ); ?></span>
<# var maxHour = data.twelveHourFormat ? 12 : 24; #>
<input type="number" size="2" maxlength="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}"" />
</label>
<span class="time-special-char date-time-separator">:</span>
<label class="minute-field">
<span class="screen-reader-text"><?php esc_html_e( 'Minute' ); ?></span>
<input type="number" size="2" maxlength="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59" />
</label>
<# if ( data.twelveHourFormat ) { #>
<label class="am-pm-field">
<span class="screen-reader-text"><?php esc_html_e( 'AM / PM' ); ?></span>
<select class="date-input" data-component="ampm">
<option value="am"><?php esc_html_e( 'AM' ); ?></option>
<option value="pm"><?php esc_html_e( 'PM' ); ?></option>
</select>
</label>
<# } #>
<abbr class="date-timezone" aria-label="<?php esc_attr_e( 'Timezone' ); ?>" title="<?php echo esc_attr( $timezone_info['description'] ); ?>"><?php echo esc_html( $timezone_info['abbr'] ); ?></abbr>
</div>
</div>
</div>
<?php
}
/**
* Generate options for the month Select.
*
* Based on touch_time().
*
* @since 4.9.0
* @see touch_time()
*
* @return array
*/
public function get_month_choices() {
global $wp_locale;
$months = array();
for ( $i = 1; $i < 13; $i++ ) {
$month_text = $wp_locale->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' ), $i, $month_text );
$months[ $i ]['value'] = $i;
}
return array(
'month_choices' => $months,
);
}
/**
* Get timezone info.
*
* @since 4.9.0
*
* @return array abbr and description.
*/
public function get_timezone_info() {
$tz_string = get_option( 'timezone_string' );
$timezone_info = array();
if ( $tz_string ) {
try {
$tz = new DateTimezone( $tz_string );
} catch ( Exception $e ) {
$tz = '';
}
if ( $tz ) {
$now = new DateTime( 'now', $tz );
$formatted_gmt_offset = sprintf( 'UTC%s', $this->format_gmt_offset( $tz->getOffset( $now ) / 3600 ) );
$tz_name = str_replace( '_', ' ', $tz->getName() );
$timezone_info['abbr'] = $now->format( 'T' );
/* translators: 1: timezone name, 2: timezone abbreviation, 3: gmt offset */
$timezone_info['description'] = sprintf( __( 'Timezone is %1$s (%2$s), currently %3$s.' ), $tz_name, $timezone_info['abbr'], $formatted_gmt_offset );
} else {
$timezone_info['description'] = '';
}
} else {
$formatted_gmt_offset = $this->format_gmt_offset( intval( get_option( 'gmt_offset', 0 ) ) );
$timezone_info['abbr'] = sprintf( 'UTC%s', $formatted_gmt_offset );
/* translators: %s: UTC offset */
$timezone_info['description'] = sprintf( __( 'Timezone is %s.' ), $timezone_info['abbr'] );
}
return $timezone_info;
}
/**
* Format GMT Offset.
*
* @since 4.9.0
* @see wp_timezone_choice()
*
* @param float $offset Offset in hours.
* @return string Formatted offset.
*/
public function format_gmt_offset( $offset ) {
if ( 0 <= $offset ) {
$formatted_offset = '+' . (string) $offset;
} else {
$formatted_offset = (string) $offset;
}
$formatted_offset = str_replace(
array( '.25', '.5', '.75' ),
array( ':15', ':30', ':45' ),
$formatted_offset
);
return $formatted_offset;
}
}

View File

@ -672,7 +672,7 @@
};
$( function() {
var bg, setValue;
var bg, setValue, handleUpdatedChangesetUuid;
api.settings = window._wpCustomizeSettings;
if ( ! api.settings ) {
@ -765,28 +765,39 @@
api.preview.send( 'scroll', $( window ).scrollTop() );
});
/**
* Handle update to changeset UUID.
*
* @param {string} uuid - UUID.
* @returns {void}
*/
handleUpdatedChangesetUuid = function( uuid ) {
api.settings.changeset.uuid = uuid;
// Update UUIDs in links and forms.
$( document.body ).find( 'a[href], area' ).each( function() {
api.prepareLinkPreview( this );
} );
$( document.body ).find( 'form' ).each( function() {
api.prepareFormPreview( this );
} );
/*
* Replace the UUID in the URL. Note that the wrapped history.replaceState()
* will handle injecting the current api.settings.changeset.uuid into the URL,
* so this is merely to trigger that logic.
*/
if ( history.replaceState ) {
history.replaceState( currentHistoryState, '', location.href );
}
};
api.preview.bind( 'changeset-uuid', handleUpdatedChangesetUuid );
api.preview.bind( 'saved', function( response ) {
if ( response.next_changeset_uuid ) {
api.settings.changeset.uuid = response.next_changeset_uuid;
// Update UUIDs in links and forms.
$( document.body ).find( 'a[href], area' ).each( function() {
api.prepareLinkPreview( this );
} );
$( document.body ).find( 'form' ).each( function() {
api.prepareFormPreview( this );
} );
/*
* Replace the UUID in the URL. Note that the wrapped history.replaceState()
* will handle injecting the current api.settings.changeset.uuid into the URL,
* so this is merely to trigger that logic.
*/
if ( history.replaceState ) {
history.replaceState( currentHistoryState, '', location.href );
}
handleUpdatedChangesetUuid( response.next_changeset_uuid );
}
api.trigger( 'saved', response );
} );

File diff suppressed because one or more lines are too long

View File

@ -547,8 +547,18 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'customize-views', "/wp-includes/js/customize-views.js", array( 'jquery', 'underscore', 'imgareaselect', 'customize-models', 'media-editor', 'media-views' ), false, 1 );
$scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base', 'wp-a11y', 'wp-util' ), false, 1 );
did_action( 'init' ) && $scripts->localize( 'customize-controls', '_wpCustomizeControlsL10n', array(
'activate' => __( 'Save &amp; Activate' ),
'save' => __( 'Save &amp; Publish' ),
'activate' => __( 'Activate &amp; Publish' ),
'save' => __( 'Save &amp; Publish' ), // @todo Remove as not required.
'publish' => __( 'Publish' ),
'published' => __( 'Published' ),
'saveDraft' => __( 'Save Draft' ),
'draftSaved' => __( 'Draft Saved' ),
'updating' => __( 'Updating' ),
'schedule' => __( 'Schedule' ),
'scheduled' => __( 'Scheduled' ),
'invalid' => __( 'Invalid' ),
'saveBeforeShare' => __( 'Please save your changes in order to share the preview.' ),
'futureDateError' => __( 'You must supply a future date to schedule.' ),
'saveAlert' => __( 'The changes you made will be lost if you navigate away from this page.' ),
'saved' => __( 'Saved' ),
'cancel' => __( 'Cancel' ),
@ -563,7 +573,7 @@ function wp_default_scripts( &$scripts ) {
'serverSaveError' => __( 'Failed connecting to the server. Please try saving again.' ),
/* translators: placeholder is URL to the Customizer to load the autosaved version */
'autosaveNotice' => __( 'There is a more recent autosave of your changes than the one you are previewing. <a href="%s">Restore the autosave</a>' ),
'videoHeaderNotice' => __( 'This theme doesn\'t support video headers on this page. Navigate to the front page or another page that supports video headers.' ),
'videoHeaderNotice' => __( 'This theme doesn\'t support video headers on this page. Navigate to the front page or another page that supports video headers.' ),
// Used for overriding the file types allowed in plupload.
'allowedFiles' => __( 'Allowed Files' ),
'customCssError' => wp_array_slice_assoc(

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.9-alpha-41625';
$wp_version = '4.9-alpha-41626';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.