Ticket #37974: 37974.1.diff
File 37974.1.diff, 37.3 KB (added by , 8 years ago) |
---|
-
src/wp-admin/css/customize-controls.css
1219 1219 outline: none; 1220 1220 } 1221 1221 1222 .reordering .add-new-item, 1222 1223 .reordering .add-new-widget, 1223 1224 .reordering .add-new-menu-item { 1224 1225 opacity: 0.2; … … 1282 1283 color: #00a0d2; 1283 1284 } 1284 1285 1286 .wp-reorder-nav { 1287 display: none; 1288 background-color: #fff; 1289 position: absolute; 1290 top: 0; 1291 right: 0; 1292 } 1293 1294 .reordering .wp-reorder-nav, 1295 .wp-reorder-nav.is-active { 1296 display: block; 1297 } 1298 1299 .wp-reorder-nav button, 1285 1300 .widget-reorder-nav span, 1286 1301 .menu-item-reorder-nav button { 1287 1302 position: relative; … … 1296 1311 outline: none; 1297 1312 } 1298 1313 1314 .wp-reorder-nav button, 1299 1315 .menu-item-reorder-nav button { 1300 1316 width: 30px; 1301 1317 height: 40px; … … 1305 1321 box-shadow: none; 1306 1322 } 1307 1323 1324 .wp-reorder-nav button:before, 1308 1325 .widget-reorder-nav span:before, 1309 1326 .menu-item-reorder-nav button:before { 1310 1327 display: inline-block; … … 1320 1337 -moz-osx-font-smoothing: grayscale; 1321 1338 } 1322 1339 1340 .wp-reorder-nav button:hover, 1341 .wp-reorder-nav button:focus, 1323 1342 .widget-reorder-nav span:hover, 1324 1343 .widget-reorder-nav span:focus, 1325 1344 .menu-item-reorder-nav button:hover, … … 1328 1347 background: #eee; 1329 1348 } 1330 1349 1350 .wp-reorder-nav button { 1351 width: 33px; 1352 height: 38px; 1353 } 1354 1355 .wp-reorder-nav button:before { 1356 font: normal 20px/38px dashicons; 1357 } 1358 1359 .move-item-down:before, 1331 1360 .move-widget-down:before, 1332 1361 .menus-move-down:before { 1333 1362 content: "\f347"; 1334 1363 } 1335 1364 1365 .move-item-up:before, 1336 1366 .move-widget-up:before, 1337 1367 .menus-move-up:before { 1338 1368 content: "\f343"; … … 1343 1373 .move-up-disabled .menus-move-up, 1344 1374 .move-down-disabled .menus-move-down, 1345 1375 .move-right-disabled .menus-move-right, 1346 .move-left-disabled .menus-move-left { 1376 .move-left-disabled .menus-move-left, 1377 .wp-item:first-child .move-item-up, 1378 .wp-item:last-child .move-item-down { 1347 1379 color: #d5d5d5; 1348 1380 background-color: #fff; 1349 1381 cursor: default; -
src/wp-admin/css/customize-post-collection.css
1 /* General 2 ------------------------------------------------------------------------------*/ 3 4 .customize-dashicon, 5 .drawer-toggle:before { 6 cursor: pointer; 7 display: inline-block; 8 font-family: dashicons; 9 font-size: 20px; 10 -webkit-font-smoothing: antialiased; 11 font-style: normal; 12 font-weight: normal; 13 line-height: 1; 14 position: relative; 15 text-align: center; 16 text-decoration: inherit; 17 vertical-align: top; 18 } 19 20 .drawer-toggle:before { 21 content: "\f132"; 22 position: relative; 23 left: -2px; 24 top: -1px; 25 transition: all 0.2s; 26 vertical-align: middle; 27 } 28 29 .customize-button-delete { 30 color: #a00; 31 } 32 33 .customize-button-delete:hover { 34 color: #f00; 35 } 36 37 .customize-button-delete.customize-dashicon:before { 38 content: "\f335"; 39 } 40 41 .customize-control.is-drawer-open .drawer-toggle:before { 42 transform: rotate( 45deg ); 43 } 44 45 46 /* Drawer 47 ------------------------------------------------------------------------------*/ 48 49 .customize-drawer { 50 background: #eee; 51 border-right: 1px solid #ddd; 52 display: block; 53 margin: 0; 54 overflow-x: hidden; 55 overflow-y: auto; 56 position: absolute; 57 top: 0; 58 right: 0; 59 bottom: 0; 60 left: -301px; 61 transition: left 0.18s; 62 visibility: hidden; 63 width: 300px; 64 z-index: 4; 65 } 66 67 .customize-drawer-notice { 68 padding: 15px; 69 } 70 71 .customize-drawer.is-open { 72 left: 0; 73 visibility: visible; 74 } 75 76 .drawer-is-open .wp-full-overlay-main { 77 left: 300px; 78 } 79 80 81 /* Sortable Item List 82 ------------------------------------------------------------------------------*/ 83 84 .wp-items-list { 85 list-style: none; 86 margin: 0 0 10px 0; 87 padding: 0; 88 position: relative; 89 } 90 91 .wp-item { 92 background: #fff; 93 margin: -1px 0 0 0; 94 padding: 0; 95 } 96 97 .wp-item-header { 98 border: 1px solid #dfdfdf; 99 background: #fff; 100 position: relative; 101 } 102 103 .wp-item-delete { 104 display: none; 105 height: 100%; 106 position: absolute; 107 top: 0; 108 right: 0; 109 bottom: 0; 110 text-align: center; 111 vertical-align: middle; 112 width: 40px; 113 } 114 115 .wp-item-title { 116 cursor: move; 117 margin: 0; 118 padding: 10px 20px; 119 position: relative; 120 word-wrap: break-word; 121 } 122 123 .wp-item.ui-sortable-helper { 124 background: #f9f9f9; 125 border: 1px solid #dfdfdf; 126 } 127 128 .wp-item.ui-sortable-placeholder { 129 background: transparent; 130 border: 1px dashed #a0a5aa; 131 margin-top: 0; 132 margin-bottom: 1px; 133 } 134 135 .wp-item:hover .wp-item-header { 136 border-color: #999; 137 z-index: 1; 138 } 139 140 .customize-control.is-drawer-open .wp-item-delete { 141 display: block; 142 } 143 144 .customize-control.is-drawer-open .wp-reorder-nav { 145 display: none; 146 } 147 148 149 /* Search 150 ------------------------------------------------------------------------------*/ 151 152 .search-group { 153 border-bottom: 1px solid #ddd; 154 margin: 0; 155 padding: 12px 15px; 156 position: relative; 157 } 158 159 .search-group-field { 160 padding: 6px 10px; 161 width: 100%; 162 } 163 164 .search-group-spinner { 165 margin: 0; 166 position: absolute; 167 top: 19px; 168 right: 20px; 169 } 170 171 .search-group-button-clear { 172 background: transparent; 173 border-width: 0; 174 cursor: pointer; 175 height: 20px; 176 padding: 0; 177 position: absolute; 178 top: 19px; 179 right: 20px; 180 text-align: center; 181 width: 20px; 182 } 183 184 185 /* Search Results 186 ------------------------------------------------------------------------------*/ 187 188 .search-results { 189 padding: 1px 0 15px; 190 } 191 192 .search-results ul { 193 margin: -2px 0 0; 194 } 195 196 .search-results-item { 197 background: #fff; 198 border-color: #ddd; 199 border-style: solid; 200 border-width: 1px 0; 201 clear: both; 202 cursor: pointer; 203 line-height: 10px; 204 margin: -1px 0 0 0; 205 padding: 10px 15px; 206 position: relative; 207 } 208 209 .search-results-item-title { 210 display: block; 211 font-size: 13px; 212 font-weight: 600; 213 line-height: 20px; 214 padding-left: 20px; 215 word-wrap: break-word; 216 } 217 218 .search-results-item-type { 219 color: #666; 220 float: right; 221 font-size: 12px; 222 line-height: 20px; 223 text-align: right; 224 } 225 226 .search-results-item-add { 227 color: #82878c; 228 height: 38px; 229 position: absolute; 230 top: 1px; 231 left: 1px; 232 width: 30px; 233 } 234 235 .search-results-item-add:before { 236 -webkit-border-radius: 50%; 237 border-radius: 50%; 238 content: "\f543"; 239 height: 20px; 240 position: relative; 241 top: 0; 242 left: 2px; 243 } 244 245 .search-results-item:hover { 246 border-color: #999; 247 color: #0073aa; 248 z-index: 1; 249 } 250 251 .search-results-item:hover .search-results-item-add:before { 252 color: #0073aa; 253 } 254 255 .search-results-item.is-selected .search-results-item-add:before { 256 content: "\f147"; 257 } -
src/wp-admin/js/customize-post-collection.js
1 (function( wp, $ ) { 2 3 if ( ! wp || ! wp.customize ) { return; } 4 5 var api = wp.customize; 6 7 api.PostCollection = api.PostCollection || {}; 8 9 api.DrawerModel = Backbone.Model.extend({ 10 defaults: { 11 status: 'closed' 12 }, 13 14 close: function() { 15 this.set( 'status', 'closed' ); 16 }, 17 18 open: function() { 19 this.set( 'status', 'open' ); 20 }, 21 22 toggle: function() { 23 if ( 'open' === this.get( 'status' ) ) { 24 this.close(); 25 } else { 26 this.open(); 27 } 28 } 29 }); 30 31 api.DrawerManager = Backbone.Collection.extend({ 32 model: api.DrawerModel, 33 34 initialize: function() { 35 this.on( 'change:status', this.closeOtherDrawers ); 36 }, 37 38 closeOtherDrawers: function( model ) { 39 if ( 'open' === model.get( 'status' ) ) { 40 _.chain( this.models ).without( model ).invoke( 'close' ); 41 } 42 } 43 }); 44 45 api.DrawerView = wp.Backbone.View.extend({ 46 tagName: 'div', 47 className: 'customize-drawer', 48 49 initialize: function( options ) { 50 this.controller = options.controller; 51 this.listenTo( this.controller, 'change:status', this.updateStatusClass ); 52 }, 53 54 updateStatusClass: function() { 55 if ( 'open' === this.controller.get( 'status' ) ) { 56 this.$el.addClass( 'is-open' ); 57 } else { 58 this.$el.removeClass( 'is-open' ); 59 } 60 } 61 }); 62 63 api.PostCollection.PostModel = Backbone.Model.extend({ 64 defaults: { 65 title: '', 66 order: 0 67 } 68 }); 69 70 api.PostCollection.PostsCollection = Backbone.Collection.extend({ 71 model: api.PostCollection.PostModel, 72 73 comparator: function( post ) { 74 return parseInt( post.get( 'order' ), 10 ); 75 } 76 }); 77 78 api.PostCollection.ControlView = wp.Backbone.View.extend({ 79 initialize: function( options ) { 80 this.control = options.control; 81 this.setting = options.setting; 82 83 this.listenTo( this.collection, 'add remove reset sort', this.updateSetting ); 84 this.listenTo( this.control.drawer, 'change:status', this.maybeTriggerSearch ); 85 this.listenTo( this.control.drawer, 'change:status', this.updateStatusClass ); 86 }, 87 88 render: function() { 89 this.views.add([ 90 new api.PostCollection.ItemListView({ 91 collection: this.collection, 92 control: this.control, 93 parent: this 94 }), 95 96 new api.PostCollection.ControlActionsView({ 97 collection: this.collection, 98 control: this.control, 99 parent: this 100 }) 101 ]); 102 103 return this; 104 }, 105 106 maybeTriggerSearch: function() { 107 if ( 'open' === this.control.drawer.get( 'status' ) && this.control.results.length < 1 ) { 108 this.control.search(); 109 } 110 }, 111 112 updateSetting: function() { 113 var postIds = this.collection.sort({ silent: true }).pluck( 'id' ).join( ',' ); 114 this.setting.set( postIds ); 115 }, 116 117 updateStatusClass: function() { 118 if ( 'open' === this.control.drawer.get( 'status' ) ) { 119 this.$el.addClass( 'is-drawer-open' ); 120 } else { 121 this.$el.removeClass( 'is-drawer-open' ); 122 } 123 } 124 }); 125 126 api.PostCollection.ControlActionsView = wp.Backbone.View.extend({ 127 className: 'actions', 128 tagName: 'div', 129 130 initialize: function( options ) { 131 this.control = options.control; 132 this.parent = options.parent; 133 }, 134 135 render: function() { 136 this.views.add([ 137 new api.PostCollection.AddNewItemButtonView({ 138 control: this.control 139 }) 140 ]); 141 142 return this; 143 } 144 }); 145 146 api.PostCollection.AddNewItemButtonView = wp.Backbone.View.extend({ 147 className: 'drawer-toggle add-new-item button button-secondary alignright', 148 tagName: 'button', 149 150 events: { 151 click: 'toggleDrawer' 152 }, 153 154 initialize: function( options ) { 155 this.control = options.control; 156 }, 157 158 render: function() { 159 this.$el.text( this.control.l10n.addPosts ); 160 return this; 161 }, 162 163 toggleDrawer: function( e ) { 164 e.preventDefault(); 165 this.control.drawer.toggle(); 166 } 167 }); 168 169 api.PostCollection.ItemListView = wp.Backbone.View.extend({ 170 className: 'wp-items-list', 171 tagName: 'ol', 172 173 initialize: function( options ) { 174 this.control = options.control; 175 176 this.listenTo( this.collection, 'add', this.addItem ); 177 this.listenTo( this.collection, 'add remove', this.updateOrder ); 178 this.listenTo( this.collection, 'reset', this.render ); 179 }, 180 181 render: function() { 182 this.$el.empty(); 183 this.collection.each( this.addItem, this ); 184 this.initializeSortable(); 185 return this; 186 }, 187 188 initializeSortable: function() { 189 this.$el.sortable({ 190 axis: 'y', 191 delay: 150, 192 forceHelperSize: true, 193 forcePlaceholderSize: true, 194 opacity: 0.6, 195 start: function( e, ui ) { 196 ui.placeholder.css( 'visibility', 'visible' ); 197 }, 198 update: _.bind(function() { 199 this.updateOrder(); 200 }, this ) 201 }); 202 }, 203 204 addItem: function( item ) { 205 var itemView = new api.PostCollection.ItemView({ 206 control: this.control, 207 model: item, 208 parent: this 209 }); 210 211 this.$el.append( itemView.render().el ); 212 }, 213 214 moveDown: function( model ) { 215 var index = this.collection.indexOf( model ), 216 $items = this.$el.children(); 217 218 if ( index < this.collection.length - 1 ) { 219 $items.eq( index ).insertAfter( $items.eq( index + 1 ) ); 220 this.updateOrder(); 221 wp.a11y.speak( this.control.l10n.movedDown ); 222 } 223 }, 224 225 moveUp: function( model ) { 226 var index = this.collection.indexOf( model ), 227 $items = this.$el.children(); 228 229 if ( index > 0 ) { 230 $items.eq( index ).insertBefore( $items.eq( index - 1 ) ); 231 this.updateOrder(); 232 wp.a11y.speak( this.control.l10n.movedUp ); 233 } 234 }, 235 236 updateOrder: function() { 237 _.each( this.$el.find( 'li' ), function( item, i ) { 238 var id = $( item ).data( 'post-id' ); 239 this.collection.get( id ).set( 'order', i ); 240 }, this ); 241 242 this.collection.sort(); 243 } 244 }); 245 246 api.PostCollection.ItemView = wp.Backbone.View.extend({ 247 tagName: 'li', 248 className: 'wp-item', 249 template: wp.template( 'wp-item' ), 250 251 events: { 252 'click .js-remove': 'destroy', 253 'click .move-item-up': 'moveUp', 254 'click .move-item-down': 'moveDown' 255 }, 256 257 initialize: function( options ) { 258 this.control = options.control; 259 this.parent = options.parent; 260 this.listenTo( this.model, 'destroy', this.remove ); 261 }, 262 263 render: function() { 264 var data = _.extend( this.model.toJSON(), { 265 l10n: this.control.l10n 266 }); 267 268 this.$el.html( this.template( data ) ); 269 this.$el.data( 'post-id', this.model.get( 'id' ) ); 270 271 return this; 272 }, 273 274 moveDown: function( e ) { 275 e.preventDefault(); 276 this.parent.moveDown( this.model ); 277 }, 278 279 moveUp: function( e ) { 280 e.preventDefault(); 281 this.parent.moveUp( this.model ); 282 }, 283 284 /** 285 * Destroy the view's model. 286 * 287 * Avoid syncing to the server by triggering an event instead of 288 * calling destroy() directly on the model. 289 */ 290 destroy: function() { 291 this.model.trigger( 'destroy', this.model ); 292 }, 293 294 remove: function() { 295 this.$el.remove(); 296 } 297 }); 298 299 api.PostCollection.DrawerNoticeView = wp.Backbone.View.extend({ 300 tagName: 'div', 301 className: 'customize-drawer-notice', 302 303 initialize: function( options ) { 304 this.control = options.control; 305 this.listenTo( this.control.state, 'change:notice', this.render ); 306 }, 307 308 render: function() { 309 var notice = this.control.state.get( 'notice' ); 310 this.$el.toggle( !! notice.length ).text( notice ); 311 return this; 312 } 313 }); 314 315 api.PostCollection.SearchGroupView = wp.Backbone.View.extend({ 316 tagName: 'div', 317 className: 'search-group', 318 template: wp.template( 'search-group' ), 319 320 events: { 321 'input input': 'search' 322 }, 323 324 initialize: function( options ) { 325 this.control = options.control; 326 this.parent = options.parent; 327 }, 328 329 render: function() { 330 this.$el.html( this.template({ l10n: this.control.l10n }) ); 331 this.$field = this.$el.find( '.search-group-field' ); 332 this.$spinner = this.$el.append( '<span class="search-group-spinner spinner" />' ).find( '.spinner' ); 333 334 this.views.add([ 335 new api.PostCollection.ClearResultsButtonView({ 336 collection: this.collection, 337 control: this.control, 338 parent: this 339 }) 340 ]); 341 342 return this; 343 }, 344 345 search: function() { 346 var view = this; 347 348 this.$spinner.addClass( 'is-active' ); 349 350 clearTimeout( this.timeout ); 351 this.timeout = setTimeout(function() { 352 view.control.search( view.$field.val() ) 353 .always(function() { 354 view.$spinner.removeClass( 'is-active' ); 355 }); 356 }, 300 ); 357 } 358 }); 359 360 api.PostCollection.ClearResultsButtonView = wp.Backbone.View.extend({ 361 tagName: 'button', 362 className: 'search-group-button-clear customize-button-delete customize-dashicon', 363 364 events: { 365 'click': 'clearResults' 366 }, 367 368 initialize: function( options ) { 369 this.control = options.control; 370 this.parent = options.parent; 371 this.listenTo( this.collection, 'add remove reset', this.toggleVisibility ); 372 }, 373 374 render: function() { 375 this.$el.html( $( '<span />', { 376 'class': 'screen-reader-text', 377 text: this.control.l10n.clearResults 378 }) ); 379 this.toggleVisibility(); 380 return this; 381 }, 382 383 clearResults: function() { 384 this.collection.reset(); 385 this.parent.$field.val( '' ); 386 }, 387 388 toggleVisibility: function() { 389 this.$el.toggle( !! this.collection.length ); 390 } 391 }); 392 393 api.PostCollection.SearchResultsView = wp.Backbone.View.extend({ 394 tagName: 'div', 395 className: 'search-results', 396 397 initialize: function( options ) { 398 this.control = options.control; 399 this.listenTo( this.collection, 'reset', this.render ); 400 }, 401 402 render: function() { 403 this.$list = this.$el.html( '<ul />' ).find( 'ul' ); 404 405 if ( this.collection.length ) { 406 this.collection.each( this.addItem, this ); 407 } else { 408 this.$el.empty(); 409 } 410 411 return this; 412 }, 413 414 addItem: function( model ) { 415 this.views.add( 'ul', new api.PostCollection.SearchResultView({ 416 control: this.control, 417 model: model 418 })); 419 } 420 }); 421 422 api.PostCollection.SearchResultView = wp.Backbone.View.extend({ 423 tagName: 'li', 424 className: 'search-results-item', 425 template: wp.template( 'search-result' ), 426 427 events: { 428 'click': 'addSection' 429 }, 430 431 initialize: function( options ) { 432 this.control = options.control; 433 this.listenTo( this.control.posts, 'add remove reset', this.updateSelectedClass ); 434 }, 435 436 render: function() { 437 var data = _.extend( this.model.toJSON(), { 438 l10n: this.control.l10n 439 }); 440 441 this.$el.html( this.template( data ) ); 442 this.updateSelectedClass(); 443 444 return this; 445 }, 446 447 addSection: function() { 448 this.control.posts.add( this.model ); 449 }, 450 451 updateSelectedClass: function() { 452 this.$el.toggleClass( 'is-selected', this.control.posts.contains( this.model ) ); 453 } 454 }); 455 456 api.PostCollection.PostCollectionControl = api.Control.extend({ 457 ready: function() { 458 var controlView, drawerView, 459 control = this, 460 section = api.section( this.section() ); 461 462 this.drawer = new api.DrawerModel(); 463 api.drawerManager.add( this.drawer ); 464 465 this.posts = new api.PostCollection.PostsCollection( this.params.posts ); 466 this.results = new api.PostCollection.PostsCollection(); 467 delete this.params.posts; 468 469 this.l10n = this.params.l10n; 470 delete this.params.l10n; 471 472 this.state = new Backbone.Model({ 473 notice: '' 474 }); 475 476 controlView = new api.PostCollection.ControlView({ 477 el: this.container, 478 collection: this.posts, 479 control: this, 480 data: this.params, 481 setting: this.setting 482 }); 483 484 controlView.render(); 485 486 drawerView = new api.DrawerView({ 487 controller: this.drawer 488 }); 489 490 drawerView.views.set([ 491 new api.PostCollection.SearchGroupView({ 492 collection: this.results, 493 control: this 494 }), 495 new api.PostCollection.DrawerNoticeView({ 496 control: this 497 }), 498 new api.PostCollection.SearchResultsView({ 499 collection: this.results, 500 control: this 501 }) 502 ]); 503 504 $( '.wp-full-overlay' ).append( drawerView.render().$el ); 505 506 section.expanded.bind(function( isOpen ) { 507 if ( ! isOpen ) { 508 control.drawer.close(); 509 } 510 }); 511 }, 512 513 search: function( query ) { 514 var control = this; 515 516 return wp.ajax.post( 'customize_find_posts', { 517 s: query, 518 post_types: this.params.postTypes, 519 //not_in: this.posts.pluck( 'id' ), 520 wp_customize: 'on', 521 _ajax_nonce: this.params.searchNonce 522 }).done(function( response ) { 523 control.results.reset( response ); 524 control.state.set( 'notice', '' ); 525 }).fail(function( response ) { 526 control.results.reset(); 527 control.state.set( 'notice', response ); 528 }); 529 } 530 }); 531 532 /** 533 * Extends wp.customize.controlConstructor with control constructor for 534 * post_collection. 535 */ 536 $.extend( api.controlConstructor, { 537 post_collection: api.PostCollection.PostCollectionControl 538 }); 539 540 /** 541 * Create a global drawer manager. 542 */ 543 api.drawerManager = new api.DrawerManager(); 544 545 /** 546 * Toggle an HTML class on the body when drawers are opened or closed. 547 */ 548 $( document ).ready(function() { 549 var $body = $( document.body ); 550 551 api.drawerManager.on( 'change:status', function() { 552 if ( api.drawerManager.findWhere({ status: 'open' }) ) { 553 $body.addClass( 'drawer-is-open' ); 554 } else { 555 $body.removeClass( 'drawer-is-open' ); 556 } 557 }); 558 }); 559 560 /** 561 * Toggle the front_page_sections control based on the 'show_on_front' 562 * setting value. 563 */ 564 api.bind( 'ready', function() { 565 api( 'show_on_front', function( setting ) { 566 api.control( 'front_page_sections', function( control ) { 567 var toggleVisibility = function( value ) { 568 control.container.toggle( 'page' === value ); 569 }; 570 571 toggleVisibility( setting() ); 572 setting.bind( toggleVisibility ); 573 }); 574 }); 575 }); 576 577 })( window.wp, jQuery ); -
src/wp-includes/canonical.php
655 655 exit; 656 656 } 657 657 } 658 659 /** 660 * Redirect front page section permalinks to the fragment on the front page. 661 * 662 * @since 4.7.0 663 */ 664 function wp_redirect_front_page_sections() { 665 $object_id = get_queried_object_id(); 666 667 if ( 668 ! current_theme_supports( 'front-page-sections' ) 669 || is_front_page() 670 || is_home() 671 || ! is_singular() 672 || ! is_front_page_section( $object_id ) 673 ) { 674 return; 675 } 676 677 wp_redirect( get_front_page_section_url( $object_id ) ); 678 exit; 679 } -
src/wp-includes/class-wp-customize-manager.php
227 227 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' ); 228 228 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' ); 229 229 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' ); 230 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-post-collection-control.php' ); 230 231 231 232 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menus-panel.php' ); 232 233 … … 289 290 290 291 add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); 291 292 add_action( 'wp_ajax_customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); 293 add_action( 'wp_ajax_customize_find_posts', array( $this, 'ajax_find_posts' ) ); 292 294 293 295 add_action( 'customize_register', array( $this, 'register_controls' ) ); 294 296 add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first … … 1963 1965 $this->register_control_type( 'WP_Customize_Cropped_Image_Control' ); 1964 1966 $this->register_control_type( 'WP_Customize_Site_Icon_Control' ); 1965 1967 $this->register_control_type( 'WP_Customize_Theme_Control' ); 1968 $this->register_control_type( 'WP_Customize_Post_Collection_Control' ); 1966 1969 1967 1970 /* Themes */ 1968 1971 … … 2295 2298 'section' => 'static_front_page', 2296 2299 'type' => 'dropdown-pages', 2297 2300 ) ); 2301 2302 if ( current_theme_supports( 'front-page-sections' ) ) { 2303 $this->add_setting( 'front_page_sections', array( 2304 'sanitize_callback' => array( $this, 'sanitize_id_list' ), 2305 ) ); 2306 2307 $this->add_control( new WP_Customize_Post_Collection_Control( $this, 'front_page_sections', array( 2308 'label' => __( 'Front page sections' ), 2309 'description' => '', 2310 'section' => 'static_front_page', 2311 'settings' => 'front_page_sections', 2312 'post_types' => get_theme_support( 'front-page-sections', 'post_types' ), 2313 'l10n' => array( 2314 'addPost' => __( 'Add Section' ), 2315 'addPosts' => __( 'Add Sections' ), 2316 'movedUp' => __( 'Section moved up' ), 2317 'movedDown' => __( 'Section moved down' ), 2318 'removePost' => __( 'Remove Section' ), 2319 'searchPosts' => __( 'Search Sections' ), 2320 'searchPostsPlaceholder' => __( 'Search sections…' ), 2321 ), 2322 ) ) ); 2323 } 2298 2324 } 2299 2325 2300 2326 /** … … 2374 2400 public function _render_custom_logo_partial() { 2375 2401 return get_custom_logo(); 2376 2402 } 2403 2404 /** 2405 * Ajax handler for finding posts. 2406 * 2407 * @since 4.7.0 2408 * 2409 * @see wp_ajax_find_posts() 2410 */ 2411 public function ajax_find_posts() { 2412 check_ajax_referer( 'find-posts' ); 2413 2414 $post_types = array(); 2415 2416 if ( ! empty( $_POST['post_types'] ) ) { 2417 $post_type_names = array_map( 'sanitize_text_field', wp_unslash( $_POST['post_types'] ) ); 2418 foreach ( $post_type_names as $post_type ) { 2419 $post_types[ $post_type ] = get_post_type_object( $post_type ); 2420 } 2421 } 2422 2423 if ( empty( $post_types ) ) { 2424 $post_types['post'] = get_post_type_object( 'post' ); 2425 } 2426 2427 $args = array( 2428 'post_type' => array_keys( $post_types ), 2429 'post_status' => 'publish', 2430 'post__not_in' => isset( $_POST['not_in'] ) ? wp_parse_id_list( $_POST['not_in'] ) : array(), 2431 'posts_per_page' => 50, 2432 ); 2433 2434 if ( ! empty( $_POST['s'] ) ) { 2435 $args['s'] = sanitize_text_field( wp_unslash( $_POST['s'] ) ); 2436 } 2437 2438 $posts = get_posts( $args ); 2439 2440 if ( ! $posts ) { 2441 wp_send_json_error( __( 'No results found.' ) ); 2442 } 2443 2444 foreach ( $posts as $post ) { 2445 $data[] = array( 2446 'id' => $post->ID, 2447 'title' => $post->post_title, 2448 'type' => get_post_type_object( $post->post_type )->labels->singular_name, 2449 ); 2450 } 2451 2452 wp_send_json_success( $data ); 2453 } 2454 2455 /** 2456 * Sanitization callback for lists of IDs. 2457 * 2458 * @since 4.7.0 2459 * 2460 * @param string $value Setting value. 2461 * @return string Comma-separated list of IDs. 2462 */ 2463 public function sanitize_id_list( $value ) { 2464 return implode( ',', array_unique( array_filter( wp_parse_id_list( $value ) ) ) ); 2465 } 2377 2466 } -
src/wp-includes/customize/class-wp-customize-post-collection-control.php
1 <?php 2 /** 3 * Customize API: WP_Customize_Post_Collection_Control class 4 * 5 * @package WordPress 6 * @subpackage Customize 7 * @since 4.7.0 8 */ 9 10 /** 11 * Customize Post Collection Control class. 12 * 13 * @since 4.7.0 14 * 15 * @see WP_Customize_Control 16 */ 17 class WP_Customize_Post_Collection_Control extends WP_Customize_Control { 18 /** 19 * Control type. 20 * 21 * @since 4.7.0 22 * @var string 23 */ 24 public $type = 'post_collection'; 25 26 /** 27 * Post types that can be added as sections.. 28 * 29 * @since 4.7.0 30 * @var array 31 */ 32 public $post_types = array( 'page', 'post' ); 33 34 /** 35 * Localization strings. 36 * 37 * @since 4.7.0 38 * @access public 39 * @var array 40 */ 41 public $l10n = array(); 42 43 /** 44 * Constructor. 45 * 46 * @since 4.7.0 47 * 48 * @param WP_Customize_Manager $manager Customizer bootstrap instance. 49 * @param string $id Control ID. 50 * @param array $args Optional. Arguments to override class property defaults. 51 */ 52 public function __construct( $manager, $id, $args = array() ) { 53 parent::__construct( $manager, $id, $args ); 54 55 $this->l10n = wp_parse_args( $this->l10n, array( 56 'addPost' => __( 'Add Post' ), 57 'addPosts' => __( 'Add Posts' ), 58 'clearResults' => __( 'Clear Results' ), 59 'moveUp' => __( 'Move up' ), 60 'moveDown' => __( 'Move down' ), 61 'movedUp' => __( 'Post moved up' ), 62 'movedDown' => __( 'Post moved down' ), 63 'removePost' => __( 'Remove Post' ), 64 'searchPosts' => __( 'Search Posts' ), 65 'searchPostsPlaceholder' => __( 'Search posts…' ), 66 ) ); 67 } 68 69 /** 70 * Enqueue control related scripts/styles. 71 * 72 * @since 4.7.0 73 */ 74 public function enqueue() { 75 wp_enqueue_style( 'customize-post-collection' ); 76 wp_enqueue_script( 'customize-post-collection' ); 77 78 add_action( 'customize_controls_print_footer_scripts', array( 'WP_Customize_Post_Collection_Control', 'print_templates' ) ); 79 } 80 81 /** 82 * Refresh the parameters passed to the JavaScript via JSON. 83 * 84 * @since 4.7.0 85 * @uses WP_Customize_Control::to_json() 86 */ 87 public function to_json() { 88 parent::to_json(); 89 90 $this->json['l10n'] = $this->l10n; 91 $this->json['posts'] = $this->get_posts(); 92 $this->json['postTypes'] = $this->post_types; 93 $this->json['searchNonce'] = wp_create_nonce( 'find-posts' ); 94 } 95 96 /** 97 * Don't render any content for this control from PHP. 98 * 99 * @since 4.7.0 100 * 101 * @see WP_Customize_Post_Collection_Control::content_template() 102 */ 103 public function render_content() {} 104 105 /** 106 * An Underscore (JS) template for this control's content (but not its container). 107 * 108 * @see WP_Customize_Control::print_template() 109 * 110 * @since 4.7.0 111 */ 112 protected function content_template() { 113 ?> 114 <label> 115 <# if ( data.label ) { #> 116 <span class="customize-control-title">{{ data.label }}</span> 117 <# } #> 118 <# if ( data.description ) { #> 119 <span class="description customize-control-description">{{{ data.description }}}</span> 120 <# } #> 121 </label> 122 <?php 123 } 124 125 /** 126 * Print JavaScript templates in the Customizer footer. 127 * 128 * @since 4.7.0 129 */ 130 public static function print_templates() { 131 ?> 132 <script type="text/html" id="tmpl-wp-item"> 133 <div class="wp-item-header"> 134 <h4 class="wp-item-title">{{ data.title }}</h4> 135 136 <button type="button" class="wp-item-delete customize-button-delete customize-dashicon button-link js-remove"> 137 <span class="screen-reader-text">{{ data.l10n.removePost }}</span> 138 </button> 139 140 <div class="wp-reorder-nav is-active"> 141 <button class="move-item-down" tabindex="0">{{ data.l10n.moveDown }}</button> 142 <button class="move-item-up" tabindex="0">{{ data.l10n.moveUp }}</button> 143 </div> 144 </div> 145 </script> 146 147 <script type="text/html" id="tmpl-search-group"> 148 <label class="screen-reader-text" for="search-group-field">{{ data.l10n.searchPosts }}</label> 149 <input type="text" id="search-group-field" placeholder="{{{ data.l10n.searchPostsPlaceholder }}}" class="search-group-field"> 150 </script> 151 152 <script type="text/html" id="tmpl-search-result"> 153 <span class="search-results-item-type">{{ data.type }}</span> 154 <span class="search-results-item-title">{{ data.title }}</span> 155 156 <button type="button" class="search-results-item-add customize-dashicon button-link"> 157 <span class="screen-reader-text">{{ data.l10n.addPost }}</span> 158 </button> 159 </script> 160 <?php 161 } 162 163 /** 164 * Retrieve posts. 165 * 166 * @since 4.7.0 167 * 168 * @return array 169 */ 170 protected function get_posts() { 171 $data = array(); 172 $value = $this->value(); 173 174 if ( ! empty( $value ) ) { 175 $posts = get_posts( array( 176 'post_type' => $this->post_types, 177 'post_status' => 'any', 178 'post__in' => array_map( 'absint', explode( ',', $value ) ), 179 'orderby' => 'post__in', 180 'posts_per_page' => 20, 181 ) ); 182 } 183 184 if ( ! empty( $posts ) ) { 185 $i = 0; 186 foreach ( $posts as $post ) { 187 $data[] = array( 188 'id' => $post->ID, 189 'title' => $post->post_title, 190 'order' => ++$i, 191 ); 192 } 193 } 194 195 return $data; 196 } 197 } -
src/wp-includes/default-filters.php
427 427 428 428 // Canonical 429 429 add_action( 'template_redirect', 'redirect_canonical' ); 430 add_action( 'template_redirect', 'wp_redirect_front_page_sections' ); 430 431 add_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 ); 431 432 432 433 // Shortcodes -
src/wp-includes/link-template.php
312 312 function get_page_link( $post = false, $leavename = false, $sample = false ) { 313 313 $post = get_post( $post ); 314 314 315 if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) ) 315 if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) ) { 316 316 $link = home_url('/'); 317 else 317 } elseif ( is_front_page_section( $post->ID ) ) { 318 $link = get_front_page_section_url( $post->ID ); 319 } else { 318 320 $link = _get_page_link( $post, $leavename, $sample ); 321 } 319 322 320 323 /** 321 324 * Filters the permalink for a page. … … 4142 4145 */ 4143 4146 return apply_filters( 'parent_theme_file_path', $path, $file ); 4144 4147 } 4148 4149 /** 4150 * Retrieve the URL for a front page section. 4151 * 4152 * @since 4.7.0 4153 * 4154 * @param int|WP_Post $post Post ID or object. 4155 * @return string 4156 */ 4157 function get_front_page_section_url( $post ) { 4158 return home_url( '#post-' . get_post( $post )->ID ); 4159 } -
src/wp-includes/post-template.php
1794 1794 echo $rows; 1795 1795 echo "</ul>"; 1796 1796 } 1797 1798 /** 1799 * Whether a post is a front page section. 1800 * 1801 * @since 4.7.0 1802 * 1803 * @param int $post_id Post ID. 1804 * @return bool 1805 */ 1806 function is_front_page_section( $post_id ) { 1807 $section_ids = array_filter( wp_parse_id_list( get_theme_mod( 'front_page_sections' ) ) ); 1808 return in_array( intval( $post_id ), $section_ids, true ); 1809 } -
src/wp-includes/script-loader.php
476 476 $scripts->add( 'customize-nav-menus', "/wp-admin/js/customize-nav-menus$suffix.js", array( 'jquery', 'wp-backbone', 'customize-controls', 'accordion', 'nav-menu' ), false, 1 ); 477 477 $scripts->add( 'customize-preview-nav-menus', "/wp-includes/js/customize-preview-nav-menus$suffix.js", array( 'jquery', 'wp-util', 'customize-preview', 'customize-selective-refresh' ), false, 1 ); 478 478 479 $scripts->add( 'customize-post-collection', "/wp-admin/js/customize-post-collection$suffix.js", array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-droppable', 'wp-backbone', 'customize-controls' ), false, 1 ); 480 479 481 $scripts->add( 'accordion', "/wp-admin/js/accordion$suffix.js", array( 'jquery' ), false, 1 ); 480 482 481 483 $scripts->add( 'shortcode', "/wp-includes/js/shortcode$suffix.js", array( 'underscore' ), false, 1 ); … … 819 821 820 822 $styles->add( 'wp-admin', false, array( 'dashicons', 'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus', 'widgets', 'site-icon', 'l10n' ) ); 821 823 822 $styles->add( 'login', "/wp-admin/css/login$suffix.css", array( 'dashicons', 'buttons', 'forms', 'l10n' ) ); 823 $styles->add( 'install', "/wp-admin/css/install$suffix.css", array( 'buttons' ) ); 824 $styles->add( 'wp-color-picker', "/wp-admin/css/color-picker$suffix.css" ); 825 $styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie', 'imgareaselect' ) ); 826 $styles->add( 'customize-widgets', "/wp-admin/css/customize-widgets$suffix.css", array( 'wp-admin', 'colors' ) ); 827 $styles->add( 'customize-nav-menus', "/wp-admin/css/customize-nav-menus$suffix.css", array( 'wp-admin', 'colors' ) ); 828 $styles->add( 'press-this', "/wp-admin/css/press-this$suffix.css", array( 'buttons' ) ); 824 $styles->add( 'login', "/wp-admin/css/login$suffix.css", array( 'dashicons', 'buttons', 'forms', 'l10n' ) ); 825 $styles->add( 'install', "/wp-admin/css/install$suffix.css", array( 'buttons' ) ); 826 $styles->add( 'wp-color-picker', "/wp-admin/css/color-picker$suffix.css" ); 827 $styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie', 'imgareaselect' ) ); 828 $styles->add( 'customize-widgets', "/wp-admin/css/customize-widgets$suffix.css", array( 'wp-admin', 'colors' ) ); 829 $styles->add( 'customize-nav-menus', "/wp-admin/css/customize-nav-menus$suffix.css", array( 'wp-admin', 'colors' ) ); 830 $styles->add( 'customize-post-collection', "/wp-admin/css/customize-post-collection$suffix.css", array( 'wp-admin', 'colors', 'customize-controls' ) ); 831 $styles->add( 'press-this', "/wp-admin/css/press-this$suffix.css", array( 'buttons' ) ); 829 832 830 833 $styles->add( 'ie', "/wp-admin/css/ie$suffix.css" ); 831 834 $styles->add_data( 'ie', 'conditional', 'lte IE 7' ); -
src/wp-includes/theme.php
1730 1730 1731 1731 return false; 1732 1732 } 1733 1734 case 'front-page-sections' : 1735 if ( ! is_array( $args ) ) { 1736 $args = array( 0 => array() ); 1737 } 1738 1739 $args[0] = wp_parse_args( $args[0], array( 1740 'post_types' => array( 'page' ), 1741 ) ); 1742 1743 break; 1733 1744 } 1734 1745 1735 1746 $_wp_theme_features[ $feature ] = $args; … … 1822 1833 case 'custom-logo' : 1823 1834 case 'custom-header' : 1824 1835 case 'custom-background' : 1836 case 'front-page-sections' : 1825 1837 if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) ) 1826 1838 return $_wp_theme_features[ $feature ][0][ $args[0] ]; 1827 1839 return false; … … 2082 2094 return; 2083 2095 } 2084 2096 2085 require_once ABSPATH . WPINC . '/class-wp-customize-manager.php'; 2097 require_once ABSPATH . WPINC . '/class-wp-customize-manager.php'; 2086 2098 $GLOBALS['wp_customize'] = new WP_Customize_Manager(); 2087 2099 } 2088 2100