Ticket #21776: 21776.7.diff
File 21776.7.diff, 21.2 KB (added by , 12 years ago) |
---|
-
wp-admin/includes/ajax-actions.php
1674 1674 } 1675 1675 1676 1676 function wp_ajax_set_post_thumbnail() { 1677 $json = ! empty( $_REQUEST['json'] ); 1678 1677 1679 $post_ID = intval( $_POST['post_id'] ); 1678 if ( !current_user_can( 'edit_post', $post_ID ) ) 1679 wp_die( -1 ); 1680 if ( !current_user_can( 'edit_post', $post_ID ) ) { 1681 $json ? wp_send_json_error() : wp_die( -1 ); 1682 } 1680 1683 $thumbnail_id = intval( $_POST['thumbnail_id'] ); 1681 1684 1682 1685 check_ajax_referer( "set_post_thumbnail-$post_ID" ); 1683 1686 1684 1687 if ( $thumbnail_id == '-1' ) { 1685 if ( delete_post_thumbnail( $post_ID ) ) 1686 wp_die( _wp_post_thumbnail_html( null, $post_ID ) ); 1687 else 1688 wp_die( 0 ); 1688 if ( delete_post_thumbnail( $post_ID ) ) { 1689 $return = _wp_post_thumbnail_html( null, $post_ID ); 1690 $json ? wp_send_json_success( $return ) : wp_die( $return ); 1691 } else { 1692 $json ? wp_send_json_error() : wp_die( 0 ); 1693 } 1689 1694 } 1690 1695 1691 if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) 1692 wp_die( _wp_post_thumbnail_html( $thumbnail_id, $post_ID ) ); 1693 wp_die( 0 ); 1696 if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) { 1697 $return = _wp_post_thumbnail_html( $thumbnail_id, $post_ID ); 1698 $json ? wp_send_json_success( $return ) : wp_die( $return ); 1699 } 1700 1701 $json ? wp_send_json_error() : wp_die( 0 ); 1694 1702 } 1695 1703 1696 1704 function wp_ajax_date_format() { -
wp-admin/includes/meta-boxes.php
1001 1001 * @since 2.9.0 1002 1002 */ 1003 1003 function post_thumbnail_meta_box( $post ) { 1004 global $_wp_additional_image_sizes; 1005 1006 ?><script type="text/javascript"> 1007 jQuery( function($) { 1008 var $element = $('#select-featured-image'), 1009 $thumbnailId = $element.find('input[name="thumbnail_id"]'), 1010 title = '<?php _e( "Choose a Featured Image" ); ?>', 1011 update = '<?php _e( "Update Featured Image" ); ?>', 1012 Attachment = wp.media.model.Attachment, 1013 frame, setFeaturedImage; 1014 1015 setFeaturedImage = function( thumbnailId ) { 1016 var selection; 1017 1018 $element.find('img').remove(); 1019 $element.toggleClass( 'has-featured-image', -1 != thumbnailId ); 1020 $thumbnailId.val( thumbnailId ); 1021 1022 if ( frame ) { 1023 selection = frame.state('library').get('selection'); 1024 1025 if ( -1 === thumbnailId ) 1026 selection.clear(); 1027 else 1028 selection.add( Attachment.get( thumbnailId ) ); 1029 } 1030 }; 1031 1032 $element.on( 'click', '.choose, img', function( event ) { 1033 var options, thumbnailId, attachment; 1034 1035 event.preventDefault(); 1036 1037 if ( frame ) { 1038 frame.open(); 1039 return; 1040 } 1041 1042 options = { 1043 title: title, 1044 library: { 1045 type: 'image' 1046 } 1047 }; 1048 1049 thumbnailId = $thumbnailId.val(); 1050 if ( '' !== thumbnailId && -1 !== thumbnailId ) { 1051 attachment = Attachment.get( thumbnailId ); 1052 attachment.fetch(); 1053 options.selection = [ attachment ]; 1054 } 1055 1056 frame = wp.media( options ); 1057 1058 frame.state('library').set( 'filterable', 'uploaded' ); 1059 1060 frame.toolbar.on( 'activate:select', function() { 1061 frame.toolbar.view().set({ 1062 select: { 1063 style: 'primary', 1064 text: update, 1065 1066 click: function() { 1067 var selection = frame.state().get('selection'), 1068 model = selection.first(), 1069 sizes = model.get('sizes'), 1070 size; 1071 1072 setFeaturedImage( model.id ); 1073 1074 // @todo: might need a size hierarchy equivalent. 1075 if ( sizes ) 1076 size = sizes['post-thumbnail'] || sizes.medium; 1077 1078 // @todo: Need a better way of accessing full size 1079 // data besides just calling toJSON(). 1080 size = size || model.toJSON(); 1081 1082 frame.close(); 1083 1084 $( '<img />', { 1085 src: size.url, 1086 width: size.width 1087 }).prependTo( $element ); 1088 } 1089 } 1090 }); 1091 }); 1092 1093 frame.toolbar.mode('select'); 1094 }); 1095 1096 $element.on( 'click', '.remove', function( event ) { 1097 event.preventDefault(); 1098 setFeaturedImage( -1 ); 1099 }); 1100 }); 1101 </script> 1102 1103 <?php 1104 $thumbnail_id = get_post_meta( $post->ID, '_thumbnail_id', true ); 1105 $thumbnail_size = isset( $_wp_additional_image_sizes['post-thumbnail'] ) ? 'post-thumbnail' : 'medium'; 1106 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, $thumbnail_size ); 1107 1108 $classes = empty( $thumbnail_id ) ? '' : 'has-featured-image'; 1109 1110 ?><div id="select-featured-image" 1111 class="<?php echo esc_attr( $classes ); ?>" 1112 data-post-id="<?php echo esc_attr( $post->ID ); ?>"> 1113 <?php echo $thumbnail_html; ?> 1114 <input type="hidden" name="thumbnail_id" value="<?php echo esc_attr( $thumbnail_id ); ?>" /> 1115 <a href="#" class="choose button-secondary"><?php _e( 'Choose a Featured Image' ); ?></a> 1116 <a href="#" class="remove"><?php _e( 'Remove Featured Image' ); ?></a> 1117 </div> 1118 <?php 1004 $thumbnail_id = get_post_meta( $post->ID, '_thumbnail_id', true ); 1005 echo _wp_post_thumbnail_html( $thumbnail_id, $post->ID ); 1119 1006 } 1007 No newline at end of file -
wp-admin/includes/post.php
199 199 set_post_format( $post_ID, false ); 200 200 } 201 201 202 // Featured Images203 if ( isset( $post_data['thumbnail_id'] ) ) {204 if ( '-1' == $post_data['thumbnail_id'] )205 delete_post_thumbnail( $post_ID );206 else207 set_post_thumbnail( $post_ID, $post_data['thumbnail_id'] );208 }209 210 202 // Meta Stuff 211 203 if ( isset($post_data['meta']) && $post_data['meta'] ) { 212 204 foreach ( $post_data['meta'] as $key => $value ) { -
wp-admin/js/custom-background.js
57 57 }); 58 58 }); 59 59 60 frame.setState('library') ;60 frame.setState('library').open(); 61 61 }); 62 62 }); 63 63 })(jQuery); 64 No newline at end of file -
wp-admin/js/custom-header.js
40 40 }); 41 41 }); 42 42 43 frame.setState('library') ;43 frame.setState('library').open(); 44 44 }); 45 45 }); 46 46 }(jQuery)); -
wp-includes/css/media-views.css
403 403 */ 404 404 .media-frame { 405 405 overflow: hidden; 406 position: absolute; 407 top: 0; 408 left: 0; 409 right: 0; 410 bottom: 0; 406 411 } 407 412 408 413 .media-frame .region-content { -
wp-includes/js/media-editor.js
375 375 376 376 workflow = workflows[ id ] = wp.media( _.defaults( options || {}, { 377 377 frame: 'post', 378 state: 'upload', 378 379 title: wp.media.view.l10n.addMedia, 379 380 multiple: true 380 381 } ) ); … … 427 428 } 428 429 }, this ); 429 430 431 workflow.state('featured-image').on( 'select', function() { 432 var settings = wp.media.view.settings, 433 featuredImage = settings.featuredImage, 434 selection = this.get('selection').single(); 435 436 if ( ! featuredImage ) 437 return; 438 439 featuredImage.id = selection ? selection.id : -1; 440 wp.media.post( 'set-post-thumbnail', { 441 json: true, 442 post_id: settings.postId, 443 thumbnail_id: featuredImage.id, 444 _wpnonce: featuredImage.nonce 445 }).done( function( html ) { 446 $( '.inside', '#postimagediv' ).html( html ); 447 }); 448 }); 449 450 workflow.setState( workflow.options.state ); 430 451 return workflow; 431 452 }, 432 453 454 id: function( id ) { 455 if ( id ) 456 return id; 457 458 // If an empty `id` is provided, default to `wpActiveEditor`. 459 id = wpActiveEditor; 460 461 // If that doesn't work, fall back to `tinymce.activeEditor.id`. 462 if ( ! id && typeof tinymce !== 'undefined' && tinymce.activeEditor ) 463 id = tinymce.activeEditor.id; 464 465 // Last but not least, fall back to the empty string. 466 id = id || ''; 467 return id; 468 }, 469 433 470 get: function( id ) { 471 id = this.id( id ); 434 472 return workflows[ id ]; 435 473 }, 436 474 437 475 remove: function( id ) { 476 id = this.id( id ); 438 477 delete workflows[ id ]; 439 478 }, 440 479 … … 497 536 } 498 537 }, 499 538 539 open: function( id ) { 540 var workflow, editor; 541 542 id = this.id( id ); 543 544 // Save a bookmark of the caret position in IE. 545 if ( typeof tinymce !== 'undefined' ) { 546 editor = tinymce.get( id ); 547 548 if ( tinymce.isIE && editor && ! editor.isHidden() ) { 549 editor.focus(); 550 editor.windowManager.insertimagebookmark = editor.selection.getBookmark(); 551 } 552 } 553 554 workflow = this.get( id ); 555 556 // Initialize the editor's workflow if we haven't yet. 557 if ( ! workflow ) 558 workflow = this.add( id ); 559 560 return workflow.open(); 561 }, 562 500 563 init: function() { 501 564 $(document.body).on( 'click', '.insert-media', function( event ) { 502 565 var $this = $(this), … … 513 576 514 577 wp.media.editor.open( editor ); 515 578 }); 516 },517 579 518 open: function( id ) { 519 var workflow, editor; 580 // Open the content media manager to the 'featured image' tab when 581 // the post thumbnail is clicked. 582 $('#postimagediv').on( 'click', '#set-post-thumbnail', function( event ) { 583 event.preventDefault(); 584 // Stop propagation to prevent thickbox from activating. 585 event.stopPropagation(); 520 586 521 // If an empty `id` is provided, default to `wpActiveEditor`. 522 id = id || wpActiveEditor; 587 // Always get the 'content' frame, since this is tailored to post.php. 588 var frame = wp.media.editor.add('content'), 589 initialState = frame.state().id, 590 escape; 523 591 524 if ( typeof tinymce !== 'undefined' && tinymce.activeEditor ) { 525 // If that doesn't work, fall back to `tinymce.activeEditor`. 526 if ( ! id ) { 527 editor = tinymce.activeEditor; 528 id = id || editor.id; 529 } else { 530 editor = tinymce.get( id ); 531 } 592 escape = function() { 593 // Only run this event once. 594 this.off( 'escape', escape ); 532 595 533 // Save a bookmark of the caret position, needed for IE 534 if ( tinymce.isIE && editor && ! editor.isHidden() ) { 535 editor.focus(); 536 editor.windowManager.insertimagebookmark = editor.selection.getBookmark(); 537 } 538 } 596 // If we're still on the 'featured-image' state, restore 597 // the initial state. 598 if ( 'featured-image' === this.state().id ) 599 this.setState( initialState ); 600 }; 539 601 540 // Last but not least, fall back to the empty string. 541 id = id || ''; 602 frame.on( 'escape', escape, frame ); 542 603 543 workflow = wp.media.editor.get( id);604 frame.setState('featured-image').open(); 544 605 545 // If the workflow exists, open it. 546 // Initialize the editor's workflow if we haven't yet. 547 if ( workflow ) 548 workflow.open(); 549 else 550 workflow = wp.media.editor.add( id ); 551 552 return workflow; 606 // Update the featured image id when the 'remove' link is clicked. 607 }).on( 'click', '#remove-post-thumbnail', function() { 608 wp.media.view.settings.featuredImage.id = -1; 609 }); 553 610 } 554 611 }; 555 612 613 _.bindAll( wp.media.editor, 'open' ); 556 614 $( wp.media.editor.init ); 557 615 }(jQuery)); -
wp-includes/js/media-models.js
30 30 frame = new MediaFrame.Post( attributes ); 31 31 32 32 delete attributes.frame; 33 // Set the default state. 34 frame.setState( frame.options.state ); 35 // Render, attach, and open the frame. 36 return frame.render().attach().open(); 33 34 return frame; 37 35 }; 38 36 39 37 _.extend( media, { model: {}, view: {}, controller: {} }); … … 235 233 236 234 // Overload the `update` request so properties can be saved. 237 235 } else if ( 'update' === method ) { 236 if ( ! this.get('nonces') ) 237 return $.Deferred().resolveWith( this ).promise(); 238 238 239 options = options || {}; 239 240 options.context = this; 240 241 -
wp-includes/js/media-views.js
169 169 // created the `states` collection, or are trying to select a state 170 170 // that does not exist. 171 171 if ( ( previous && id === previous.id ) || ! this.states || ! this.states.get( id ) ) 172 return ;172 return this; 173 173 174 174 if ( previous ) { 175 175 previous.trigger('deactivate'); … … 178 178 179 179 this._state = id; 180 180 this.state().trigger('activate'); 181 182 return this; 181 183 }, 182 184 183 185 // Returns the previous active state. … … 547 549 } 548 550 }); 549 551 552 // wp.media.controller.FeaturedImage 553 // --------------------------------- 554 media.controller.FeaturedImage = media.controller.Library.extend({ 555 defaults: _.defaults({ 556 id: 'featured-image', 557 filterable: 'uploaded', 558 multiple: false, 559 menu: 'main', 560 toolbar: 'featured-image' 561 }, media.controller.Library.prototype.defaults ), 550 562 563 initialize: function() { 564 // If we haven't been provided a `library`, create a `Selection`. 565 if ( ! this.get('library') ) 566 this.set( 'library', media.query({ type: 'image' }) ); 567 568 media.controller.Library.prototype.initialize.apply( this, arguments ); 569 }, 570 571 activate: function() { 572 var selection = this.get('selection'), 573 id = media.view.settings.featuredImage.id; 574 575 if ( '' !== id && -1 !== id ) { 576 attachment = Attachment.get( id ); 577 attachment.fetch(); 578 } 579 580 selection.reset( attachment ? [ attachment ] : [] ); 581 media.controller.Library.prototype.activate.apply( this, arguments ); 582 } 583 }); 584 585 551 586 // wp.media.controller.Embed 552 587 // ------------------------- 553 588 media.controller.Embed = media.controller.State.extend({ … … 603 638 }, this ); 604 639 605 640 this.set( 'url', '' ); 606 this.frame.toolbar.view().refresh(); 641 642 if ( this.id === this.frame.state().id ) 643 this.frame.toolbar.view().refresh(); 607 644 } 608 645 }); 609 646 … … 1075 1112 if ( this.options.modal ) { 1076 1113 this.modal = new media.view.Modal({ 1077 1114 controller: this, 1078 $content: this.$el,1079 1115 title: this.options.title 1080 1116 }); 1117 1118 this.modal.content( this ); 1081 1119 } 1082 1120 1083 1121 // Force the uploader off if the upload limit has been exceeded or … … 1100 1138 this.on( 'attach', _.bind( this.views.ready, this.views ), this ); 1101 1139 }, 1102 1140 1103 render: function() {1104 if ( this.modal )1105 this.modal.render();1106 1107 media.view.Frame.prototype.render.apply( this, arguments );1108 return this;1109 },1110 1111 1141 createIframeStates: function( options ) { 1112 1142 var settings = media.view.settings, 1113 1143 tabs = settings.tabs, … … 1184 1214 }); 1185 1215 1186 1216 // Map some of the modal's methods to the frame. 1187 _.each(['open','close','attach','detach' ], function( method ) {1217 _.each(['open','close','attach','detach','escape'], function( method ) { 1188 1218 media.view.MediaFrame.prototype[ method ] = function( view ) { 1189 1219 if ( this.modal ) 1190 1220 this.modal[ method ].apply( this.modal, arguments ); … … 1200 1230 media.view.MediaFrame.prototype.initialize.apply( this, arguments ); 1201 1231 1202 1232 _.defaults( this.options, { 1203 state: 'upload',1204 1233 selection: [], 1205 1234 library: {}, 1206 1235 multiple: false … … 1347 1376 media.view.MediaFrame.Post = media.view.MediaFrame.Select.extend({ 1348 1377 initialize: function() { 1349 1378 _.defaults( this.options, { 1350 state: 'upload',1351 1379 multiple: true, 1352 1380 editing: false 1353 1381 }); … … 1407 1435 libraryState: 'gallery-edit' 1408 1436 }) 1409 1437 ]); 1438 1439 1440 if ( media.view.settings.featuredImage ) { 1441 this.states.add( new media.controller.FeaturedImage({ 1442 controller: this, 1443 menu: 'main' 1444 }) ); 1445 } 1410 1446 }, 1411 1447 1412 1448 bindHandlers: function() { … … 1425 1461 toolbar: { 1426 1462 'main-attachments': 'mainAttachmentsToolbar', 1427 1463 'main-embed': 'mainEmbedToolbar', 1464 'featured-image': 'featuredImageToolbar', 1428 1465 'gallery-edit': 'galleryEditToolbar', 1429 1466 'gallery-add': 'galleryAddToolbar' 1430 1467 } … … 1442 1479 media.view.MediaFrame.Select.prototype.mainMenu.call( this, { silent: true }); 1443 1480 1444 1481 this.menu.view().set({ 1445 separateLibrary: new media.View({1482 'library-separator': new media.View({ 1446 1483 className: 'separator', 1447 1484 priority: 60 1448 1485 }), 1449 embed: {1486 'embed': { 1450 1487 text: l10n.fromUrlTitle, 1451 1488 priority: 80 1452 1489 } 1453 1490 }); 1491 1492 if ( media.view.settings.featuredImage ) { 1493 this.menu.view().set( 'featured-image', { 1494 text: l10n.featuredImageTitle, 1495 priority: 100 1496 }); 1497 } 1454 1498 }, 1455 1499 1456 1500 galleryMenu: function() { … … 1557 1601 }) ); 1558 1602 }, 1559 1603 1604 featuredImageToolbar: function() { 1605 this.toolbar.view( new media.view.Toolbar.Select({ 1606 controller: this, 1607 text: l10n.setFeaturedImage, 1608 state: this.options.state || 'upload' 1609 }) ); 1610 }, 1611 1560 1612 mainEmbedToolbar: function() { 1561 1613 this.toolbar.view( new media.view.Toolbar.Embed({ 1562 1614 controller: this … … 1627 1679 }, 1628 1680 1629 1681 events: { 1630 'click .media-modal-backdrop, .media-modal-close': ' closeHandler',1682 'click .media-modal-backdrop, .media-modal-close': 'escapeHandler', 1631 1683 'keydown': 'keydown' 1632 1684 }, 1633 1685 … … 1641 1693 }); 1642 1694 }, 1643 1695 1644 render: function() { 1645 // Ensure content div exists. 1646 this.options.$content = this.options.$content || $('<div />'); 1647 1648 // Detach the content element from the DOM to prevent 1649 // `this.$el.html()` from garbage collecting its events. 1650 this.options.$content.detach(); 1651 1652 this.$el.html( this.template({ 1696 prepare: function() { 1697 return { 1653 1698 title: this.options.title 1654 }) ); 1655 1656 this.options.$content.addClass('media-modal-content'); 1657 this.$('.media-modal').append( this.options.$content ); 1658 return this; 1699 }; 1659 1700 }, 1660 1701 1661 1702 attach: function() { 1703 if ( this.views.attached ) 1704 return this; 1705 1706 if ( ! this.views.rendered ) 1707 this.render(); 1708 1662 1709 this.$el.appendTo( this.options.container ); 1710 1711 // Manually mark the view as attached and trigger ready. 1712 this.views.attached = true; 1713 this.views.ready(); 1714 1663 1715 return this.propagate('attach'); 1664 1716 }, 1665 1717 1666 1718 detach: function() { 1719 if ( this.$el.is(':visible') ) 1720 this.close(); 1721 1667 1722 this.$el.detach(); 1723 this.views.attached = false; 1668 1724 return this.propagate('detach'); 1669 1725 }, 1670 1726 1671 1727 open: function() { 1728 if ( this.$el.is(':visible') ) 1729 return this; 1730 1731 if ( ! this.views.attached ) 1732 this.attach(); 1733 1672 1734 this.$el.show().focus(); 1673 1735 return this.propagate('open'); 1674 1736 }, 1675 1737 1676 close: function() { 1738 close: function( options ) { 1739 if ( ! this.views.attached || ! this.$el.is(':visible') ) 1740 return this; 1741 1677 1742 this.$el.hide(); 1678 return this.propagate('close'); 1743 this.propagate('close'); 1744 1745 if ( options && options.escape ) 1746 this.propagate('escape'); 1747 1748 return this; 1679 1749 }, 1680 1750 1681 closeHandler: function( event ) { 1751 escape: function() { 1752 return this.close({ escape: true }); 1753 }, 1754 1755 escapeHandler: function( event ) { 1682 1756 event.preventDefault(); 1683 this. close();1757 this.escape(); 1684 1758 }, 1685 1759 1686 content: function( $content ) { 1687 // Detach any existing content to prevent events from being lost. 1688 if ( this.options.$content ) 1689 this.options.$content.detach(); 1690 1691 // Set and render the content. 1692 this.options.$content = ( $content instanceof Backbone.View ) ? $content.$el : $content; 1693 return this.render(); 1760 content: function( content ) { 1761 this.views.set( '.media-modal-content', content ); 1762 return this; 1694 1763 }, 1695 1764 1696 1765 // Triggers a modal event and if the `propagate` option is set, … … 1708 1777 // Close the modal when escape is pressed. 1709 1778 if ( 27 === event.which ) { 1710 1779 event.preventDefault(); 1711 this. close();1780 this.escape(); 1712 1781 return; 1713 1782 } 1714 1783 } -
wp-includes/media.php
1433 1433 if ( isset( $args['post'] ) ) { 1434 1434 $post = get_post( $args['post'] ); 1435 1435 $settings['postId'] = $post->ID; 1436 1437 if ( current_theme_supports( 'post-thumbnails', $post->post_type ) && post_type_supports( $post->post_type, 'thumbnail' ) ) { 1438 1439 $featuredImageId = get_post_meta( $post->ID, '_thumbnail_id', true ); 1440 1441 $settings['featuredImage'] = array( 1442 'id' => $featuredImageId ? $featuredImageId : -1, 1443 'nonce' => wp_create_nonce( 'set_post_thumbnail-' . $post->ID ), 1444 ); 1445 } 1436 1446 } 1437 1447 1438 1448 $hier = $post && is_post_type_hierarchical( $post->post_type ); … … 1466 1476 // From URL 1467 1477 'fromUrlTitle' => __( 'From URL' ), 1468 1478 1479 // Featured Images 1480 'featuredImageTitle' => __( 'Featured Image' ), 1481 'setFeaturedImage' => __( 'Set featured image' ), 1482 1469 1483 // Gallery 1470 1484 'createGalleryTitle' => __( 'Create Gallery' ), 1471 1485 'editGalleryTitle' => __( 'Edit Gallery' ), … … 1508 1522 <div class="media-modal wp-core-ui"> 1509 1523 <h3 class="media-modal-title">{{ data.title }}</h3> 1510 1524 <a class="media-modal-close media-modal-icon" href="#" title="<?php esc_attr_e('Close'); ?>"></a> 1525 <div class="media-modal-content"></div> 1511 1526 </div> 1512 1527 <div class="media-modal-backdrop"> 1513 1528 <div></div>