mirror of
https://github.com/WordPress/WordPress.git
synced 2024-11-10 12:50:18 +01:00
Customize: Allow users to more seamlessly create page-based nav menus during customization.
Introduces the ability to create stubs for the various post types to add to a given menu. This eliminates the need to leave the customizer to first create the post in the admin and then return to managing menus. Only the title of the newly-created post can be supplied; the post content will be blank and will need to be provided in the normal edit post screen outside the customizer, unless a plugin enables a post editing in the customizer experience. When a post is created and added to a nav menu in the customizer, the newly created post that is added to a menu is given the `auto-draft` status, and if the changes are not published, the `auto-draft` post will be automatically deleted within 7 days via `wp_delete_auto_drafts()`. However, if the customizer changes are saved, then these nav menu item `auto-draft` post stubs will be transitioned to `publish`. Includes portions of code from the Customize Posts <https://github.com/xwp/wp-customize-posts> and Front-end Editor <https://github.com/iseulde/wp-front-end-editor> plugins. For more information, see https://make.wordpress.org/core/2016/06/16/feature-proposal-content-authorship-in-menus-with-live-preview/ Props celloexpressions, westonruter, valendesigns, afercia, melchoyce, mapk, iseulde, mrahmadawais. Fixes #34923. Built from https://develop.svn.wordpress.org/trunk@38436 git-svn-id: http://core.svn.wordpress.org/trunk@38377 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
42c4653c9a
commit
abd9cdc07b
@ -1219,7 +1219,8 @@ body.cheatin p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.add-new-widget:before,
|
.add-new-widget:before,
|
||||||
.add-new-menu-item:before {
|
.add-new-menu-item:before,
|
||||||
|
#available-menu-items .new-content-item .add-content:before {
|
||||||
content: "\f132";
|
content: "\f132";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
2
wp-admin/css/customize-controls-rtl.min.css
vendored
2
wp-admin/css/customize-controls-rtl.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1219,7 +1219,8 @@ body.cheatin p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.add-new-widget:before,
|
.add-new-widget:before,
|
||||||
.add-new-menu-item:before {
|
.add-new-menu-item:before,
|
||||||
|
#available-menu-items .new-content-item .add-content:before {
|
||||||
content: "\f132";
|
content: "\f132";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
2
wp-admin/css/customize-controls.min.css
vendored
2
wp-admin/css/customize-controls.min.css
vendored
File diff suppressed because one or more lines are too long
@ -61,6 +61,10 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customize-control-nav_menu_item.has-notifications .menu-item-handle {
|
||||||
|
border-right: 4px solid #00a0d2;
|
||||||
|
}
|
||||||
|
|
||||||
.wp-customizer .menu-item-settings {
|
.wp-customizer .menu-item-settings {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -497,7 +501,7 @@
|
|||||||
color: #23282d;
|
color: #23282d;
|
||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .accordion-section-content {
|
#available-menu-items .available-menu-items-list {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */
|
max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@ -534,9 +538,58 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .accordion-section-content {
|
#available-menu-items .accordion-section-content {
|
||||||
padding: 1px 15px 15px 15px;
|
|
||||||
margin: 0;
|
|
||||||
max-height: 290px;
|
max-height: 290px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .available-menu-items-list {
|
||||||
|
margin: 0 0 45px 0;
|
||||||
|
padding: 1px 15px 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .available-menu-items-list:only-child { /* Types that do not support new items for the current user */
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-custom-menu-item .accordion-section-content {
|
||||||
|
padding: 0 15px 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .new-content-item {
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
padding: 8px 15px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: #eee;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -moz-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .new-content-item .create-item-input {
|
||||||
|
-webkit-box-flex: 10;
|
||||||
|
-webkit-flex-grow: 10;
|
||||||
|
-moz-box-flex: 10;
|
||||||
|
-ms-flex-positive: 10;
|
||||||
|
-ms-flex: 10;
|
||||||
|
flex-grow: 10;
|
||||||
|
margin-right: 5px;
|
||||||
|
padding: 4.5px;
|
||||||
|
}
|
||||||
|
#available-menu-items .new-content-item .add-content {
|
||||||
|
padding-right: 6px;
|
||||||
|
-webkit-box-flex: 10;
|
||||||
|
-webkit-flex-grow: 10;
|
||||||
|
-moz-box-flex: 10;
|
||||||
|
-ms-flex-positive: 10;
|
||||||
|
-ms-flex: 10;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .menu-item-tpl {
|
#available-menu-items .menu-item-tpl {
|
||||||
@ -546,7 +599,9 @@
|
|||||||
#custom-menu-item-name.invalid,
|
#custom-menu-item-name.invalid,
|
||||||
#custom-menu-item-url.invalid,
|
#custom-menu-item-url.invalid,
|
||||||
.menu-name-field.invalid,
|
.menu-name-field.invalid,
|
||||||
.menu-name-field.invalid:focus {
|
.menu-name-field.invalid:focus,
|
||||||
|
#available-menu-items .new-content-item .create-item-input.invalid,
|
||||||
|
#available-menu-items .new-content-item .create-item-input.invalid:focus {
|
||||||
border: 1px solid #f00;
|
border: 1px solid #f00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
wp-admin/css/customize-nav-menus-rtl.min.css
vendored
2
wp-admin/css/customize-nav-menus-rtl.min.css
vendored
File diff suppressed because one or more lines are too long
@ -61,6 +61,10 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customize-control-nav_menu_item.has-notifications .menu-item-handle {
|
||||||
|
border-left: 4px solid #00a0d2;
|
||||||
|
}
|
||||||
|
|
||||||
.wp-customizer .menu-item-settings {
|
.wp-customizer .menu-item-settings {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -497,7 +501,7 @@
|
|||||||
color: #23282d;
|
color: #23282d;
|
||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .accordion-section-content {
|
#available-menu-items .available-menu-items-list {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */
|
max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@ -534,9 +538,58 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .accordion-section-content {
|
#available-menu-items .accordion-section-content {
|
||||||
padding: 1px 15px 15px 15px;
|
|
||||||
margin: 0;
|
|
||||||
max-height: 290px;
|
max-height: 290px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .available-menu-items-list {
|
||||||
|
margin: 0 0 45px 0;
|
||||||
|
padding: 1px 15px 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .available-menu-items-list:only-child { /* Types that do not support new items for the current user */
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-custom-menu-item .accordion-section-content {
|
||||||
|
padding: 0 15px 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .accordion-section-content .new-content-item {
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
padding: 8px 15px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: #eee;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -moz-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#available-menu-items .new-content-item .create-item-input {
|
||||||
|
-webkit-box-flex: 10;
|
||||||
|
-webkit-flex-grow: 10;
|
||||||
|
-moz-box-flex: 10;
|
||||||
|
-ms-flex-positive: 10;
|
||||||
|
-ms-flex: 10;
|
||||||
|
flex-grow: 10;
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 4.5px;
|
||||||
|
}
|
||||||
|
#available-menu-items .new-content-item .add-content {
|
||||||
|
padding-left: 6px;
|
||||||
|
-webkit-box-flex: 10;
|
||||||
|
-webkit-flex-grow: 10;
|
||||||
|
-moz-box-flex: 10;
|
||||||
|
-ms-flex-positive: 10;
|
||||||
|
-ms-flex: 10;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#available-menu-items .menu-item-tpl {
|
#available-menu-items .menu-item-tpl {
|
||||||
@ -546,7 +599,9 @@
|
|||||||
#custom-menu-item-name.invalid,
|
#custom-menu-item-name.invalid,
|
||||||
#custom-menu-item-url.invalid,
|
#custom-menu-item-url.invalid,
|
||||||
.menu-name-field.invalid,
|
.menu-name-field.invalid,
|
||||||
.menu-name-field.invalid:focus {
|
.menu-name-field.invalid:focus,
|
||||||
|
#available-menu-items .new-content-item .create-item-input.invalid,
|
||||||
|
#available-menu-items .new-content-item .create-item-input.invalid:focus {
|
||||||
border: 1px solid #f00;
|
border: 1px solid #f00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
wp-admin/css/customize-nav-menus.min.css
vendored
2
wp-admin/css/customize-nav-menus.min.css
vendored
File diff suppressed because one or more lines are too long
@ -80,6 +80,47 @@
|
|||||||
});
|
});
|
||||||
api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems );
|
api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems );
|
||||||
|
|
||||||
|
api.Menus.insertedAutoDrafts = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new `auto-draft` post.
|
||||||
|
*
|
||||||
|
* @param {object} params - Parameters for the draft post to create.
|
||||||
|
* @param {string} params.post_type - Post type to add.
|
||||||
|
* @param {string} params.post_title - Post title to use.
|
||||||
|
* @return {jQuery.promise} Promise resolved with the added post.
|
||||||
|
*/
|
||||||
|
api.Menus.insertAutoDraftPost = function insertAutoDraftPost( params ) {
|
||||||
|
var request, deferred = $.Deferred();
|
||||||
|
|
||||||
|
request = wp.ajax.post( 'customize-nav-menus-insert-auto-draft', {
|
||||||
|
'customize-menus-nonce': api.settings.nonce['customize-menus'],
|
||||||
|
'wp_customize': 'on',
|
||||||
|
'params': params
|
||||||
|
} );
|
||||||
|
|
||||||
|
request.done( function( response ) {
|
||||||
|
if ( response.post_id ) {
|
||||||
|
deferred.resolve( response );
|
||||||
|
api.Menus.insertedAutoDrafts.push( response.post_id );
|
||||||
|
api( 'nav_menus_created_posts' ).set( _.clone( api.Menus.insertedAutoDrafts ) );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
request.fail( function( response ) {
|
||||||
|
var error = response || '';
|
||||||
|
|
||||||
|
if ( 'undefined' !== typeof response.message ) {
|
||||||
|
error = response.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error( error );
|
||||||
|
deferred.rejectWith( error );
|
||||||
|
} );
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wp.customize.Menus.AvailableMenuItemsPanelView
|
* wp.customize.Menus.AvailableMenuItemsPanelView
|
||||||
*
|
*
|
||||||
@ -100,6 +141,8 @@
|
|||||||
'click .menu-item-tpl': '_submit',
|
'click .menu-item-tpl': '_submit',
|
||||||
'click #custom-menu-item-submit': '_submitLink',
|
'click #custom-menu-item-submit': '_submitLink',
|
||||||
'keypress #custom-menu-item-name': '_submitLink',
|
'keypress #custom-menu-item-name': '_submitLink',
|
||||||
|
'click .new-content-item .add-content': '_submitNew',
|
||||||
|
'keypress .create-item-input': '_submitNew',
|
||||||
'keydown': 'keyboardAccessible'
|
'keydown': 'keyboardAccessible'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -115,6 +158,7 @@
|
|||||||
pages: {},
|
pages: {},
|
||||||
sectionContent: '',
|
sectionContent: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
|
addingNew: false,
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -124,7 +168,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$search = $( '#menu-items-search' );
|
this.$search = $( '#menu-items-search' );
|
||||||
this.sectionContent = this.$el.find( '.accordion-section-content' );
|
this.sectionContent = this.$el.find( '.available-menu-items-list' );
|
||||||
|
|
||||||
this.debounceSearch = _.debounce( self.search, 500 );
|
this.debounceSearch = _.debounce( self.search, 500 );
|
||||||
|
|
||||||
@ -160,7 +204,7 @@
|
|||||||
|
|
||||||
// Load more items.
|
// Load more items.
|
||||||
this.sectionContent.scroll( function() {
|
this.sectionContent.scroll( function() {
|
||||||
var totalHeight = self.$el.find( '.accordion-section.open .accordion-section-content' ).prop( 'scrollHeight' ),
|
var totalHeight = self.$el.find( '.accordion-section.open .available-menu-items-list' ).prop( 'scrollHeight' ),
|
||||||
visibleHeight = self.$el.find( '.accordion-section.open' ).height();
|
visibleHeight = self.$el.find( '.accordion-section.open' ).height();
|
||||||
|
|
||||||
if ( ! self.loading && $( this ).scrollTop() > 3 / 4 * totalHeight - visibleHeight ) {
|
if ( ! self.loading && $( this ).scrollTop() > 3 / 4 * totalHeight - visibleHeight ) {
|
||||||
@ -337,7 +381,7 @@
|
|||||||
}
|
}
|
||||||
items = new api.Menus.AvailableItemCollection( items ); // @todo Why is this collection created and then thrown away?
|
items = new api.Menus.AvailableItemCollection( items ); // @todo Why is this collection created and then thrown away?
|
||||||
self.collection.add( items.models );
|
self.collection.add( items.models );
|
||||||
typeInner = availableMenuItemContainer.find( '.accordion-section-content' );
|
typeInner = availableMenuItemContainer.find( '.available-menu-items-list' );
|
||||||
items.each(function( menuItem ) {
|
items.each(function( menuItem ) {
|
||||||
typeInner.append( itemTemplate( menuItem.attributes ) );
|
typeInner.append( itemTemplate( menuItem.attributes ) );
|
||||||
});
|
});
|
||||||
@ -356,13 +400,15 @@
|
|||||||
|
|
||||||
// Adjust the height of each section of items to fit the screen.
|
// Adjust the height of each section of items to fit the screen.
|
||||||
itemSectionHeight: function() {
|
itemSectionHeight: function() {
|
||||||
var sections, totalHeight, accordionHeight, diff;
|
var sections, lists, totalHeight, accordionHeight, diff;
|
||||||
totalHeight = window.innerHeight;
|
totalHeight = window.innerHeight;
|
||||||
sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' );
|
sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' );
|
||||||
accordionHeight = 46 * ( 2 + sections.length ) - 13; // Magic numbers.
|
lists = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")' );
|
||||||
|
accordionHeight = 46 * ( 1 + sections.length ) + 14; // Magic numbers.
|
||||||
diff = totalHeight - accordionHeight;
|
diff = totalHeight - accordionHeight;
|
||||||
if ( 120 < diff && 290 > diff ) {
|
if ( 120 < diff && 290 > diff ) {
|
||||||
sections.css( 'max-height', diff );
|
sections.css( 'max-height', diff );
|
||||||
|
lists.css( 'max-height', ( diff - 60 ) );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -456,6 +502,88 @@
|
|||||||
itemName.val( '' );
|
itemName.val( '' );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Submit handler for keypress (enter) on field and click on button.
|
||||||
|
_submitNew: function( event ) {
|
||||||
|
var container;
|
||||||
|
|
||||||
|
// Only proceed with keypress if it is Enter.
|
||||||
|
if ( 'keypress' === event.type && 13 !== event.which ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.addingNew ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
container = $( event.target ).closest( '.accordion-section' );
|
||||||
|
|
||||||
|
this.submitNew( container );
|
||||||
|
},
|
||||||
|
|
||||||
|
// Creates a new object and adds an associated menu item to the menu.
|
||||||
|
submitNew: function( container ) {
|
||||||
|
var panel = this,
|
||||||
|
itemName = container.find( '.create-item-input' ),
|
||||||
|
title = itemName.val(),
|
||||||
|
dataContainer = container.find( '.available-menu-items-list' ),
|
||||||
|
itemType = dataContainer.data( 'type' ),
|
||||||
|
itemObject = dataContainer.data( 'object' ),
|
||||||
|
itemTypeLabel = dataContainer.data( 'type_label' ),
|
||||||
|
promise;
|
||||||
|
|
||||||
|
if ( ! this.currentMenuControl ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only posts are supported currently.
|
||||||
|
if ( 'post_type' !== itemType ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( '' === $.trim( itemName.val() ) ) {
|
||||||
|
itemName.addClass( 'invalid' );
|
||||||
|
itemName.focus();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
itemName.removeClass( 'invalid' );
|
||||||
|
container.find( '.accordion-section-title' ).addClass( 'loading' );
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.addingNew = true;
|
||||||
|
itemName.attr( 'disabled', 'disabled' );
|
||||||
|
promise = api.Menus.insertAutoDraftPost( {
|
||||||
|
post_title: title,
|
||||||
|
post_type: itemObject
|
||||||
|
} );
|
||||||
|
promise.done( function( data ) {
|
||||||
|
var availableItem, $content, itemTemplate;
|
||||||
|
availableItem = new api.Menus.AvailableItemModel( {
|
||||||
|
'id': 'post-' + data.post_id, // Used for available menu item Backbone models.
|
||||||
|
'title': itemName.val(),
|
||||||
|
'type': itemType,
|
||||||
|
'type_label': itemTypeLabel,
|
||||||
|
'object': itemObject,
|
||||||
|
'object_id': data.post_id,
|
||||||
|
'url': data.url
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Add new item to menu.
|
||||||
|
panel.currentMenuControl.addItemToMenu( availableItem.attributes );
|
||||||
|
|
||||||
|
// Add the new item to the list of available items.
|
||||||
|
api.Menus.availableMenuItemsPanel.collection.add( availableItem );
|
||||||
|
$content = container.find( '.available-menu-items-list' );
|
||||||
|
itemTemplate = wp.template( 'available-menu-item' );
|
||||||
|
$content.prepend( itemTemplate( availableItem.attributes ) );
|
||||||
|
$content.scrollTop();
|
||||||
|
|
||||||
|
// Reset the create content form.
|
||||||
|
itemName.val( '' ).removeAttr( 'disabled' );
|
||||||
|
panel.addingNew = false;
|
||||||
|
container.find( '.accordion-section-title' ).removeClass( 'loading' );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
// Opens the panel.
|
// Opens the panel.
|
||||||
open: function( menuControl ) {
|
open: function( menuControl ) {
|
||||||
this.currentMenuControl = menuControl;
|
this.currentMenuControl = menuControl;
|
||||||
@ -2545,6 +2673,9 @@
|
|||||||
if ( data.nav_menu_updates || data.nav_menu_item_updates ) {
|
if ( data.nav_menu_updates || data.nav_menu_item_updates ) {
|
||||||
api.Menus.applySavedData( data );
|
api.Menus.applySavedData( data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset list of inserted auto draft post IDs.
|
||||||
|
api.Menus.insertedAutoDrafts = [];
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Open and focus menu control.
|
// Open and focus menu control.
|
||||||
|
4
wp-admin/js/customize-nav-menus.min.js
vendored
4
wp-admin/js/customize-nav-menus.min.js
vendored
File diff suppressed because one or more lines are too long
@ -56,16 +56,16 @@ final class WP_Customize_Nav_Menus {
|
|||||||
add_filter( 'customize_refresh_nonces', array( $this, 'filter_nonces' ) );
|
add_filter( 'customize_refresh_nonces', array( $this, 'filter_nonces' ) );
|
||||||
add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) );
|
add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) );
|
||||||
add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) );
|
add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) );
|
||||||
|
add_action( 'wp_ajax_customize-nav-menus-insert-auto-draft', array( $this, 'ajax_insert_auto_draft_post' ) );
|
||||||
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||||
|
|
||||||
// Needs to run after core Navigation section is set up.
|
|
||||||
add_action( 'customize_register', array( $this, 'customize_register' ), 11 );
|
add_action( 'customize_register', array( $this, 'customize_register' ), 11 );
|
||||||
|
|
||||||
add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_dynamic_setting_args' ), 10, 2 );
|
add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_dynamic_setting_args' ), 10, 2 );
|
||||||
add_filter( 'customize_dynamic_setting_class', array( $this, 'filter_dynamic_setting_class' ), 10, 3 );
|
add_filter( 'customize_dynamic_setting_class', array( $this, 'filter_dynamic_setting_class' ), 10, 3 );
|
||||||
add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_templates' ) );
|
add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_templates' ) );
|
||||||
add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) );
|
add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) );
|
||||||
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
|
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
|
||||||
|
add_action( 'customize_preview_init', array( $this, 'make_auto_draft_status_previewable' ) );
|
||||||
|
add_action( 'customize_save_nav_menus_created_posts', array( $this, 'save_nav_menus_created_posts' ) );
|
||||||
|
|
||||||
// Selective Refresh partials.
|
// Selective Refresh partials.
|
||||||
add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 );
|
add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 );
|
||||||
@ -626,6 +626,12 @@ final class WP_Customize_Nav_Menus {
|
|||||||
'section' => 'add_menu',
|
'section' => 'add_menu',
|
||||||
'settings' => array(),
|
'settings' => array(),
|
||||||
) ) );
|
) ) );
|
||||||
|
|
||||||
|
$this->manager->add_setting( new WP_Customize_Filter_Setting( $this->manager, 'nav_menus_created_posts', array(
|
||||||
|
'transport' => 'postMessage',
|
||||||
|
'default' => array(),
|
||||||
|
'sanitize_callback' => array( $this, 'sanitize_nav_menus_created_posts' ),
|
||||||
|
) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -648,6 +654,7 @@ final class WP_Customize_Nav_Menus {
|
|||||||
* Return an array of all the available item types.
|
* Return an array of all the available item types.
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
|
* @since 4.7.0 Each array item now includes a `$type_label` in in addition to `$title`, `$type`, and `$object`.
|
||||||
* @access public
|
* @access public
|
||||||
*
|
*
|
||||||
* @return array The available menu item types.
|
* @return array The available menu item types.
|
||||||
@ -660,6 +667,7 @@ final class WP_Customize_Nav_Menus {
|
|||||||
foreach ( $post_types as $slug => $post_type ) {
|
foreach ( $post_types as $slug => $post_type ) {
|
||||||
$item_types[] = array(
|
$item_types[] = array(
|
||||||
'title' => $post_type->labels->name,
|
'title' => $post_type->labels->name,
|
||||||
|
'type_label' => $post_type->labels->singular_name,
|
||||||
'type' => 'post_type',
|
'type' => 'post_type',
|
||||||
'object' => $post_type->name,
|
'object' => $post_type->name,
|
||||||
);
|
);
|
||||||
@ -674,6 +682,7 @@ final class WP_Customize_Nav_Menus {
|
|||||||
}
|
}
|
||||||
$item_types[] = array(
|
$item_types[] = array(
|
||||||
'title' => $taxonomy->labels->name,
|
'title' => $taxonomy->labels->name,
|
||||||
|
'type_label' => $taxonomy->labels->singular_name,
|
||||||
'type' => 'taxonomy',
|
'type' => 'taxonomy',
|
||||||
'object' => $taxonomy->name,
|
'object' => $taxonomy->name,
|
||||||
);
|
);
|
||||||
@ -684,6 +693,7 @@ final class WP_Customize_Nav_Menus {
|
|||||||
* Filters the available menu item types.
|
* Filters the available menu item types.
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
|
* @since 4.7.0 Each array item now includes a `$type_label` in in addition to `$title`, `$type`, and `$object`.
|
||||||
*
|
*
|
||||||
* @param array $item_types Custom menu item types.
|
* @param array $item_types Custom menu item types.
|
||||||
*/
|
*/
|
||||||
@ -692,6 +702,119 @@ final class WP_Customize_Nav_Menus {
|
|||||||
return $item_types;
|
return $item_types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new `auto-draft` post.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param array $postarr {
|
||||||
|
* Abbreviated post array.
|
||||||
|
*
|
||||||
|
* @var string $post_title Post title.
|
||||||
|
* @var string $post_type Post type.
|
||||||
|
* }
|
||||||
|
* @return WP_Post|WP_Error Inserted auto-draft post object or error.
|
||||||
|
*/
|
||||||
|
public function insert_auto_draft_post( $postarr ) {
|
||||||
|
if ( ! isset( $postarr['post_type'] ) || ! post_type_exists( $postarr['post_type'] ) ) {
|
||||||
|
return new WP_Error( 'unknown_post_type', __( 'Unknown post type' ) );
|
||||||
|
}
|
||||||
|
if ( ! isset( $postarr['post_title'] ) ) {
|
||||||
|
$postarr['post_title'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
add_filter( 'wp_insert_post_empty_content', '__return_false', 1000 );
|
||||||
|
$args = array(
|
||||||
|
'post_status' => 'auto-draft',
|
||||||
|
'post_type' => $postarr['post_type'],
|
||||||
|
'post_title' => $postarr['post_title'],
|
||||||
|
'post_name' => sanitize_title( $postarr['post_title'] ), // Auto-drafts are allowed to have empty post_names, so we need to explicitly set it.
|
||||||
|
);
|
||||||
|
$r = wp_insert_post( wp_slash( $args ), true );
|
||||||
|
remove_filter( 'wp_insert_post_empty_content', '__return_false', 1000 );
|
||||||
|
|
||||||
|
if ( is_wp_error( $r ) ) {
|
||||||
|
return $r;
|
||||||
|
} else {
|
||||||
|
return get_post( $r );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajax handler for adding a new auto-draft post.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @since 4.7.0
|
||||||
|
*/
|
||||||
|
public function ajax_insert_auto_draft_post() {
|
||||||
|
if ( ! check_ajax_referer( 'customize-menus', 'customize-menus-nonce', false ) ) {
|
||||||
|
status_header( 400 );
|
||||||
|
wp_send_json_error( 'bad_nonce' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'customize' ) ) {
|
||||||
|
status_header( 403 );
|
||||||
|
wp_send_json_error( 'customize_not_allowed' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( $_POST['params'] ) || ! is_array( $_POST['params'] ) ) {
|
||||||
|
status_header( 400 );
|
||||||
|
wp_send_json_error( 'missing_params' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = wp_array_slice_assoc(
|
||||||
|
array_merge(
|
||||||
|
array(
|
||||||
|
'post_type' => '',
|
||||||
|
'post_title' => '',
|
||||||
|
),
|
||||||
|
wp_unslash( $_POST['params'] )
|
||||||
|
),
|
||||||
|
array( 'post_type', 'post_title' )
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( empty( $params['post_type'] ) || ! post_type_exists( $params['post_type'] ) ) {
|
||||||
|
status_header( 400 );
|
||||||
|
wp_send_json_error( 'missing_post_type_param' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$post_type_object = get_post_type_object( $params['post_type'] );
|
||||||
|
if ( ! current_user_can( $post_type_object->cap->create_posts ) || ! current_user_can( $post_type_object->cap->publish_posts ) ) {
|
||||||
|
status_header( 403 );
|
||||||
|
wp_send_json_error( 'insufficient_post_permissions' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$params['post_title'] = trim( $params['post_title'] );
|
||||||
|
if ( '' === $params['post_title'] ) {
|
||||||
|
status_header( 400 );
|
||||||
|
wp_send_json_error( 'missing_post_title' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = $this->insert_auto_draft_post( $params );
|
||||||
|
if ( is_wp_error( $r ) ) {
|
||||||
|
$error = $r;
|
||||||
|
if ( ! empty( $post_type_object->labels->singular_name ) ) {
|
||||||
|
$singular_name = $post_type_object->labels->singular_name;
|
||||||
|
} else {
|
||||||
|
$singular_name = __( 'Post' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
/* translators: %1$s is the post type name and %2$s is the error message. */
|
||||||
|
'message' => sprintf( __( '%1$s could not be created: %2$s' ), $singular_name, $error->get_error_message() ),
|
||||||
|
);
|
||||||
|
wp_send_json_error( $data );
|
||||||
|
} else {
|
||||||
|
$post = $r;
|
||||||
|
$data = array(
|
||||||
|
'post_id' => $post->ID,
|
||||||
|
'url' => get_permalink( $post->ID ),
|
||||||
|
);
|
||||||
|
wp_send_json_success( $data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the JavaScript templates used to render Menu Customizer components.
|
* Print the JavaScript templates used to render Menu Customizer components.
|
||||||
*
|
*
|
||||||
@ -768,7 +891,7 @@ final class WP_Customize_Nav_Menus {
|
|||||||
<span class="spinner"></span>
|
<span class="spinner"></span>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button>
|
<button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button>
|
||||||
<ul class="accordion-section-content" data-type="search"></ul>
|
<ul class="accordion-section-content available-menu-items-list" data-type="search"></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="new-custom-menu-item" class="accordion-section">
|
<div id="new-custom-menu-item" class="accordion-section">
|
||||||
<h4 class="accordion-section-title" role="presentation">
|
<h4 class="accordion-section-title" role="presentation">
|
||||||
@ -797,7 +920,8 @@ final class WP_Customize_Nav_Menus {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
// Containers for per-post-type item browsing; items added with JS.
|
|
||||||
|
// Containers for per-post-type item browsing; items are added with JS.
|
||||||
foreach ( $this->available_item_types() as $available_item_type ) {
|
foreach ( $this->available_item_types() as $available_item_type ) {
|
||||||
$id = sprintf( 'available-menu-items-%s-%s', $available_item_type['type'], $available_item_type['object'] );
|
$id = sprintf( 'available-menu-items-%s-%s', $available_item_type['type'], $available_item_type['object'] );
|
||||||
?>
|
?>
|
||||||
@ -813,7 +937,20 @@ final class WP_Customize_Nav_Menus {
|
|||||||
<span class="toggle-indicator" aria-hidden="true"></span>
|
<span class="toggle-indicator" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
</h4>
|
</h4>
|
||||||
<ul class="accordion-section-content" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>"></ul>
|
<div class="accordion-section-content">
|
||||||
|
<?php if ( 'post_type' === $available_item_type['type'] ) : ?>
|
||||||
|
<?php $post_type_obj = get_post_type_object( $available_item_type['object'] ); ?>
|
||||||
|
<?php if ( current_user_can( $post_type_obj->cap->create_posts ) && current_user_can( $post_type_obj->cap->publish_posts ) ) : ?>
|
||||||
|
<div class="new-content-item">
|
||||||
|
<input type="text" class="create-item-input" placeholder="<?php
|
||||||
|
/* translators: %s: Singular title of post type or taxonomy */
|
||||||
|
printf( __( 'Create New %s' ), $post_type_obj->labels->singular_name ); ?>">
|
||||||
|
<button type="button" class="button add-content"><?php _e( 'Add' ); ?></button>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<ul class="available-menu-items-list" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>" data-type_label="<?php echo esc_attr( isset( $available_item_type['type_label'] ) ? $available_item_type['type_label'] : $available_item_type['type'] ); ?>"></ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
@ -880,6 +1017,70 @@ final class WP_Customize_Nav_Menus {
|
|||||||
add_filter( 'customize_render_partials_response', array( $this, 'export_partial_rendered_nav_menu_instances' ) );
|
add_filter( 'customize_render_partials_response', array( $this, 'export_partial_rendered_nav_menu_instances' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the auto-draft status protected so that it can be queried.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function make_auto_draft_status_previewable() {
|
||||||
|
global $wp_post_statuses;
|
||||||
|
$wp_post_statuses['auto-draft']->protected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize post IDs for auto-draft posts created for nav menu items to be published.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param array $value Post IDs.
|
||||||
|
* @returns array Post IDs.
|
||||||
|
*/
|
||||||
|
public function sanitize_nav_menus_created_posts( $value ) {
|
||||||
|
$post_ids = array();
|
||||||
|
foreach ( wp_parse_id_list( $value ) as $post_id ) {
|
||||||
|
if ( empty( $post_id ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$post = get_post( $post_id );
|
||||||
|
if ( 'auto-draft' !== $post->post_status ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$post_type_obj = get_post_type_object( $post->post_type );
|
||||||
|
if ( ! $post_type_obj ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( ! current_user_can( $post_type_obj->cap->publish_posts ) || ! current_user_can( $post_type_obj->cap->edit_post, $post_id ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$post_ids[] = $post->ID;
|
||||||
|
}
|
||||||
|
return $post_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish the auto-draft posts that were created for nav menu items.
|
||||||
|
*
|
||||||
|
* The post IDs will have been sanitized by already by
|
||||||
|
* `WP_Customize_Nav_Menu_Items::sanitize_nav_menus_created_posts()` to
|
||||||
|
* remove any post IDs for which the user cannot publish or for which the
|
||||||
|
* post is not an auto-draft.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param WP_Customize_Setting $setting Customizer setting object.
|
||||||
|
*/
|
||||||
|
public function save_nav_menus_created_posts( $setting ) {
|
||||||
|
$post_ids = $setting->post_value();
|
||||||
|
if ( ! empty( $post_ids ) ) {
|
||||||
|
foreach ( $post_ids as $post_id ) {
|
||||||
|
wp_publish_post( $post_id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep track of the arguments that are being passed to wp_nav_menu().
|
* Keep track of the arguments that are being passed to wp_nav_menu().
|
||||||
*
|
*
|
||||||
|
@ -498,6 +498,8 @@ class WP_Customize_Setting {
|
|||||||
/**
|
/**
|
||||||
* Fetch and sanitize the $_POST value for the setting.
|
* Fetch and sanitize the $_POST value for the setting.
|
||||||
*
|
*
|
||||||
|
* During a save request prior to save, post_value() provides the new value while value() does not.
|
||||||
|
*
|
||||||
* @since 3.4.0
|
* @since 3.4.0
|
||||||
*
|
*
|
||||||
* @param mixed $default A default value which is used as a fallback. Default is null.
|
* @param mixed $default A default value which is used as a fallback. Default is null.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '4.7-alpha-38435';
|
$wp_version = '4.7-alpha-38436';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
Loading…
Reference in New Issue
Block a user