Make WordPress Core

Ticket #29145: 29145.2.diff

File 29145.2.diff, 17.0 KB (added by wonderboymusic, 10 years ago)
  • src/wp-admin/includes/ajax-actions.php

     
    21612161        ) ) );
    21622162
    21632163        $query['post_type'] = 'attachment';
    2164         $query['post_status'] = 'inherit';
     2164        if ( MEDIA_TRASH
     2165                && ! empty( $_REQUEST['query']['post_status'] )
     2166                && 'trash' === $_REQUEST['query']['post_status'] ) {
     2167                $query['post_status'] = 'trash';
     2168        } else {
     2169                $query['post_status'] = 'inherit';
     2170        }
     2171
    21652172        if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
    21662173                $query['post_status'] .= ',private';
    21672174
     
    22162223        if ( isset( $changes['description'] ) )
    22172224                $post['post_content'] = $changes['description'];
    22182225
     2226        if ( MEDIA_TRASH && isset( $changes['status'] ) )
     2227                $post['post_status'] = $changes['status'];
     2228
    22192229        if ( isset( $changes['alt'] ) ) {
    22202230                $alt = wp_unslash( $changes['alt'] );
    22212231                if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) {
     
    22432253                }
    22442254        }
    22452255
    2246         wp_update_post( $post );
     2256        if ( MEDIA_TRASH && isset( $changes['status'] ) && 'trash' === $changes['status'] ) {
     2257                wp_delete_post( $id );
     2258        } else {
     2259                wp_update_post( $post );
     2260        }
     2261
    22472262        wp_send_json_success();
    22482263}
    22492264
  • src/wp-includes/css/media-views.css

     
    16031603.attachment-info .edit-attachment,
    16041604.attachment-info .refresh-attachment,
    16051605.attachment-info .delete-attachment,
    1606 .attachment-info .trash-attachment {
     1606.attachment-info .trash-attachment,
     1607.attachment-info .untrash-attachment {
    16071608        display: block;
    16081609        text-decoration: none;
    16091610        white-space: nowrap;
     
    16201621}
    16211622
    16221623.media-modal .delete-attachment,
    1623 .media-modal .trash-attachment {
     1624.media-modal .trash-attachment,
     1625.media-modal .untrash-attachment {
    16241626        color: #bc0b0b;
    16251627}
    16261628
    16271629.media-modal .delete-attachment:hover,
    1628 .media-modal .trash-attachment:hover {
     1630.media-modal .trash-attachment:hover,
     1631.media-modal .untrash-attachment:hover {
    16291632        color: red;
    16301633}
    16311634
     
    27382741        max-height: calc( 100% - 42px ); /* leave space for actions underneath */
    27392742}
    27402743
    2741 .edit-attachment-frame .delete-attachment {
     2744.edit-attachment-frame .delete-attachment,
     2745.edit-attachment-frame .trash-attachment,
     2746.edit-attachment-frame .untrash-attachment {
    27422747        float: right;
    27432748        margin-top: 7px;
    27442749}
  • src/wp-includes/js/media-grid.js

     
    180180                        // Create a new EditAttachment frame, passing along the library and the attachment model.
    181181                        wp.media( {
    182182                                frame:       'edit-attachments',
    183                                 gridRouter:  this.gridRouter,
     183                                controller:  this,
    184184                                library:     this.state().get('library'),
    185185                                model:       model
    186186                        } );
     
    227227                },
    228228
    229229                bindDeferred: function() {
     230                        if ( ! this.browserView.dfd ) {
     231                                return;
     232                        }
    230233                        this.browserView.dfd.done( _.bind( this.startHistory, this ) );
    231234                },
    232235
     
    349352                regions:   [ 'title', 'content' ],
    350353
    351354                events: {
    352                         'click':                    'collapse',
    353                         'click .delete-media-item': 'deleteMediaItem',
    354355                        'click .left':              'previousMediaItem',
    355356                        'click .right':             'nextMediaItem'
    356357                },
    357358
    358359                initialize: function() {
    359                         var self = this;
    360 
    361360                        media.view.Frame.prototype.initialize.apply( this, arguments );
    362361
    363362                        _.defaults( this.options, {
     
    365364                                state: 'edit-attachment'
    366365                        });
    367366
    368                         this.gridRouter = this.options.gridRouter;
    369 
     367                        this.controller = this.options.controller;
     368                        this.gridRouter = this.controller.gridRouter;
    370369                        this.library = this.options.library;
    371370
    372371                        if ( this.options.model ) {
    373372                                this.model = this.options.model;
    374373                        } else {
     374                                // this is a hack
    375375                                this.model = this.library.at( 0 );
    376376                        }
    377377
     378                        this.bindHandlers();
     379                        this.createStates();
     380                        this.createModal();
     381
     382                        this.title.mode( 'default' );
     383
     384                        this.options.hasPrevious = this.hasPrevious();
     385                        this.options.hasNext = this.hasNext();
     386                },
     387
     388                bindHandlers: function() {
     389                        // Bind default title creation.
     390                        this.on( 'title:create:default', this.createTitle, this );
     391
    378392                        // Close the modal if the attachment is deleted.
    379                         this.listenTo( this.model, 'destroy', this.close, this );
     393                        this.listenTo( this.model, 'change:status destroy', this.close, this );
    380394
    381                         this.createStates();
    382 
    383395                        this.on( 'content:create:edit-metadata', this.editMetadataMode, this );
    384396                        this.on( 'content:create:edit-image', this.editImageMode, this );
    385397                        this.on( 'content:render:edit-image', this.editImageModeRender, this );
    386398                        this.on( 'close', this.detach );
     399                },
    387400
    388                         // Bind default title creation.
    389                         this.on( 'title:create:default', this.createTitle, this );
    390                         this.title.mode( 'default' );
     401                createModal: function() {
     402                        var self = this;
    391403
    392                         this.options.hasPrevious = this.hasPrevious();
    393                         this.options.hasNext = this.hasNext();
    394 
    395404                        // Initialize modal container view.
    396405                        if ( this.options.modal ) {
    397406                                this.modal = new media.view.Modal({
     
    604613        media.view.DeleteSelectedButton = media.view.Button.extend({
    605614                initialize: function() {
    606615                        media.view.Button.prototype.initialize.apply( this, arguments );
     616                        if ( this.options.filters ) {
     617                                this.listenTo( this.options.filters.model, 'change', this.filterChange );
     618                        }
    607619                        this.listenTo( this.controller, 'selection:toggle', this.toggleDisabled );
    608620                },
    609621
     622                filterChange: function( model ) {
     623                        if ( 'trash' === model.get( 'status' ) ) {
     624                                this.model.set( 'text', l10n.untrashSelected );
     625                        } else if ( media.view.settings.mediaTrash ) {
     626                                this.model.set( 'text', l10n.trashSelected );
     627                        } else {
     628                                this.model.set( 'text', l10n.deleteSelected );
     629                        }
     630                },
     631
    610632                toggleDisabled: function() {
    611                         this.$el.attr( 'disabled', ! this.controller.state().get( 'selection' ).length );
     633                        this.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length );
    612634                },
    613635
    614636                render: function() {
    615637                        media.view.Button.prototype.render.apply( this, arguments );
    616                         this.$el.addClass( 'delete-selected-button hidden' );
     638                        if ( this.controller.isModeActive( 'select' ) ) {
     639                                this.$el.addClass( 'delete-selected-button' );
     640                        } else {
     641                                this.$el.addClass( 'delete-selected-button hidden' );
     642                        }
    617643                        return this;
    618644                }
    619645        });
  • src/wp-includes/js/media-models.js

     
    824824                /**
    825825                 * @access private
    826826                 */
    827                 _requery: function() {
     827                _requery: function( cache ) {
     828                        var props;
    828829                        if ( this.props.get('query') ) {
    829                                 this.mirror( Query.get( this.props.toJSON() ) );
     830                                props = this.props.toJSON();
     831                                props.cache = ( true !== cache );
     832                                this.mirror( Query.get( props ) );
    830833                        }
    831834                },
    832835                /**
     
    947950                                }
    948951
    949952                                return uploadedTo === attachment.get('uploadedTo');
     953                        },
     954                        /**
     955                         * @static
     956                         * @param {wp.media.model.Attachment} attachment
     957                         *
     958                         * @this wp.media.model.Attachments
     959                         *
     960                         * @returns {Boolean}
     961                         */
     962                        status: function( attachment ) {
     963                                var status = this.props.get('status');
     964                                if ( _.isUndefined( status ) ) {
     965                                        return true;
     966                                }
     967
     968                                return status === attachment.get('status');
    950969                        }
    951970                }
    952971        });
     
    11441163                        'type':      'post_mime_type',
    11451164                        'perPage':   'posts_per_page',
    11461165                        'menuOrder': 'menu_order',
    1147                         'uploadedTo': 'post_parent'
     1166                        'uploadedTo': 'post_parent',
     1167                        'status':     'post_status'
    11481168                },
    11491169                /**
    11501170                 * @static
     
    11691189                                var args     = {},
    11701190                                        orderby  = Query.orderby,
    11711191                                        defaults = Query.defaultProps,
    1172                                         query;
     1192                                        query,
     1193                                        cache    = !! props.cache;
    11731194
    11741195                                // Remove the `query` property. This isn't linked to a query,
    11751196                                // this *is* the query.
    11761197                                delete props.query;
     1198                                delete props.cache;
    11771199
    11781200                                // Fill default args.
    11791201                                _.defaults( props, defaults );
     
    12071229                                args.orderby = orderby.valuemap[ props.orderby ] || props.orderby;
    12081230
    12091231                                // Search the query cache for matches.
    1210                                 query = _.find( queries, function( query ) {
    1211                                         return _.isEqual( query.args, args );
    1212                                 });
     1232                                if ( cache ) {
     1233                                        query = _.find( queries, function( query ) {
     1234                                                return _.isEqual( query.args, args );
     1235                                        });
     1236                                } else {
     1237                                        queries = [];
     1238                                }
    12131239
    12141240                                // Otherwise, create a new query and add it to the cache.
    12151241                                if ( ! query ) {
  • src/wp-includes/js/media-views.js

     
    56715671                                filters[ key ] = {
    56725672                                        text: text,
    56735673                                        props: {
     5674                                                status:  null,
    56745675                                                type:    key,
    56755676                                                uploadedTo: null,
    56765677                                                orderby: 'date',
     
    56825683                        filters.all = {
    56835684                                text:  l10n.allMediaItems,
    56845685                                props: {
     5686                                        status:  null,
    56855687                                        type:    null,
    56865688                                        uploadedTo: null,
    56875689                                        orderby: 'date',
     
    56945696                                filters.uploaded = {
    56955697                                        text:  l10n.uploadedToThisPost,
    56965698                                        props: {
     5699                                                status:  null,
    56975700                                                type:    null,
    56985701                                                uploadedTo: media.view.settings.post.id,
    56995702                                                orderby: 'menuOrder',
     
    57065709                        filters.unattached = {
    57075710                                text:  l10n.unattached,
    57085711                                props: {
     5712                                        status:     null,
    57095713                                        uploadedTo: 0,
    57105714                                        type:       null,
    57115715                                        orderby:    'menuOrder',
     
    57145718                                priority: 50
    57155719                        };
    57165720
     5721                        if ( media.view.settings.mediaTrash ) {
     5722                                filters.trash = {
     5723                                        text:  l10n.trash,
     5724                                        props: {
     5725                                                uploadedTo: null,
     5726                                                status:     'trash',
     5727                                                type:       null,
     5728                                                orderby:    'date',
     5729                                                order:      'DESC'
     5730                                        },
     5731                                        priority: 50
     5732                                };
     5733                        }
     5734
    57175735                        this.filters = filters;
    57185736                }
    57195737        });
     
    57655783                },
    57665784
    57675785                createToolbar: function() {
    5768                         var filters,
    5769                                 LibraryViewSwitcher,
    5770                                 FiltersConstructor;
     5786                        var LibraryViewSwitcher, Filters;
    57715787
    57725788                        /**
    57735789                         * @member {wp.media.view.Toolbar}
     
    57785794
    57795795                        this.views.add( this.toolbar );
    57805796
     5797                        this.toolbar.set( 'spinner', new media.view.Spinner({
     5798                                priority: -60
     5799                        }) );
     5800
     5801                        if ( -1 !== $.inArray( this.options.filters, [ 'uploaded', 'all' ] ) ) {
     5802                                // "Filters" will return a <select>, need to render
     5803                                // screen reader text before
     5804                                this.toolbar.set( 'filtersLabel', new media.view.Label({
     5805                                        value: l10n.filterByType,
     5806                                        attributes: {
     5807                                                'for':  'media-attachment-filters'
     5808                                        },
     5809                                        priority:   -80
     5810                                }).render() );
     5811
     5812                                if ( 'uploaded' === this.options.filters ) {
     5813                                        this.toolbar.set( 'filters', new media.view.AttachmentFilters.Uploaded({
     5814                                                controller: this.controller,
     5815                                                model:      this.collection.props,
     5816                                                priority:   -80
     5817                                        }).render() );
     5818                                } else {
     5819                                        Filters = new media.view.AttachmentFilters.All({
     5820                                                controller: this.controller,
     5821                                                model:      this.collection.props,
     5822                                                priority:   -80
     5823                                        });
     5824
     5825                                        this.toolbar.set( 'filters', Filters.render() );
     5826                                }
     5827                        }
     5828
    57815829                        // Feels odd to bring the global media library switcher into the Attachment
    57825830                        // browser view. Is this a use case for doAction( 'add:toolbar-items:attachments-browser', this.toolbar );
    57835831                        // which the controller can tap into and add this view?
     
    58145862                                }).render() );
    58155863
    58165864                                this.toolbar.set( 'deleteSelectedButton', new media.view.DeleteSelectedButton({
     5865                                        filters: Filters,
    58175866                                        style: 'primary',
    58185867                                        disabled: true,
    5819                                         text: l10n.deleteSelected,
     5868                                        text: media.view.settings.mediaTrash ? l10n.trashSelected : l10n.deleteSelected,
    58205869                                        controller: this.controller,
    58215870                                        priority: -60,
    58225871                                        click: function() {
    5823                                                 while ( this.controller.state().get( 'selection' ).length > 0 ) {
    5824                                                         this.controller.state().get( 'selection' ).at( 0 ).destroy();
     5872                                                var model, changed = [],
     5873                                                        selection = this.controller.state().get( 'selection' ),
     5874                                                        library = this.controller.state().get( 'library' );
     5875
     5876                                                while ( selection.length > 0 ) {
     5877                                                        model = selection.at( 0 );
     5878                                                        if ( media.view.settings.mediaTrash && 'trash' === model.get( 'status' ) ) {
     5879                                                                model.set( 'status', 'inherit' );
     5880                                                                changed.push( model.save() );
     5881                                                                selection.remove( model );
     5882                                                        } else if ( media.view.settings.mediaTrash ) {
     5883                                                                model.set( 'status', 'trash' );
     5884                                                                changed.push( model.save() );
     5885                                                                selection.remove( model );
     5886                                                        } else {
     5887                                                                model.destroy();
     5888                                                        }
    58255889                                                }
     5890
     5891                                                if ( changed.length ) {
     5892                                                        $.when( changed ).then( function() {
     5893                                                                library._requery( true );
     5894                                                        } );
     5895                                                }
    58265896                                        }
    58275897                                }).render() );
    58285898                        }
    58295899
    5830                         this.toolbar.set( 'spinner', new media.view.Spinner({
    5831                                 priority: -60
    5832                         }) );
    5833 
    5834                         filters = this.options.filters;
    5835                         if ( 'uploaded' === filters ) {
    5836                                 FiltersConstructor = media.view.AttachmentFilters.Uploaded;
    5837                         } else if ( 'all' === filters ) {
    5838                                 FiltersConstructor = media.view.AttachmentFilters.All;
    5839                         }
    5840 
    5841                         if ( FiltersConstructor ) {
    5842                                 // "FiltersConstructor" will return a <select>, need to render
    5843                                 // screen reader text before
    5844                                 this.toolbar.set( 'filtersLabel', new media.view.Label({
    5845                                         value: l10n.filterByType,
    5846                                         attributes: {
    5847                                                 'for':  'media-attachment-filters'
    5848                                         },
    5849                                         priority:   -80
    5850                                 }).render() );
    5851                                 this.toolbar.set( 'filters', new FiltersConstructor({
    5852                                         controller: this.controller,
    5853                                         model:      this.collection.props,
    5854                                         priority:   -80
    5855                                 }).render() );
    5856                         }
    5857 
    58585900                        if ( this.options.search ) {
    58595901                                // Search is an input, screen reader text needs to be rendered before
    58605902                                this.toolbar.set( 'searchLabel', new media.view.Label({
     
    64206462                        'change [data-setting] textarea': 'updateSetting',
    64216463                        'click .delete-attachment':       'deleteAttachment',
    64226464                        'click .trash-attachment':        'trashAttachment',
     6465                        'click .untrash-attachment':      'untrashAttachment',
    64236466                        'click .edit-attachment':         'editAttachment',
    64246467                        'click .refresh-attachment':      'refreshAttachment',
    64256468                        'keydown':                        'toggleSelectionHandler'
     
    64536496                 * @param {Object} event
    64546497                 */
    64556498                trashAttachment: function( event ) {
     6499                        var library = this.controller.library;
    64566500                        event.preventDefault();
    64576501
    6458                         this.model.destroy();
     6502                        if ( media.view.settings.mediaTrash ) {
     6503                                this.model.set( 'status', 'trash' );
     6504                                this.model.save().done( function() {
     6505                                        library._requery( true );
     6506                                } );
     6507                        }  else {
     6508                                this.model.destroy();
     6509                        }
    64596510                },
    64606511                /**
    64616512                 * @param {Object} event
    64626513                 */
     6514                untrashAttachment: function( event ) {
     6515                        var library = this.controller.library;
     6516                        event.preventDefault();
     6517
     6518                        this.model.set( 'status', 'inherit' );
     6519                        this.model.save().done( function() {
     6520                                library._requery( true );
     6521                        } );
     6522                },
     6523                /**
     6524                 * @param {Object} event
     6525                 */
    64636526                editAttachment: function( event ) {
    64646527                        var editState = this.controller.states.get( 'edit-image' );
    64656528                        if ( window.imageEdit && editState ) {
  • src/wp-includes/media-template.php

     
    316316
    317317                                        <# if ( ! data.uploading && data.can.remove ) { #>
    318318                                                <?php if ( MEDIA_TRASH ): ?>
     319                                                <# if ( 'trash' === data.status ) { #>
     320                                                        <a class="untrash-attachment" href="#"><?php _e( 'Untrash' ); ?></a>
     321                                                <# } else { #>
    319322                                                        <a class="trash-attachment" href="#"><?php _e( 'Trash' ); ?></a>
     323                                                <# } #>
    320324                                                <?php else: ?>
    321325                                                        <a class="delete-attachment" href="#"><?php _e( 'Delete Permanently' ); ?></a>
    322326                                                <?php endif; ?>
  • src/wp-includes/media.php

     
    28692869                'embedMimes'   => $ext_mimes,
    28702870                'contentWidth' => $content_width,
    28712871                'months'       => $months,
     2872                'mediaTrash'   => MEDIA_TRASH ? 1 : 0
    28722873        );
    28732874
    28742875        $post = null;
     
    29312932                'noItemsFound'           => __( 'No items found.' ),
    29322933                'insertIntoPost'         => $hier ? __( 'Insert into page' ) : __( 'Insert into post' ),
    29332934                'unattached'             => __( 'Unattached' ),
     2935                'trash'                  => __( 'Trash' ),
    29342936                'uploadedToThisPost'     => $hier ? __( 'Uploaded to this page' ) : __( 'Uploaded to this post' ),
    29352937                'warnDelete'             => __( "You are about to permanently delete this item.\n  'Cancel' to stop, 'OK' to delete." ),
    29362938                'warnBulkDelete'         => __( "You are about to permanently delete these items.\n  'Cancel' to stop, 'OK' to delete." ),
    29372939                'bulkSelect'             => __( 'Bulk Select' ),
    29382940                'cancelSelection'        => __( 'Cancel Selection' ),
     2941                'trashSelected'          => __( 'Trash Selected' ),
     2942                'untrashSelected'        => __( 'Untrash Selected' ),
    29392943                'deleteSelected'         => __( 'Delete Selected' ),
    29402944                'deletePermanently'      => __( 'Delete Permanently' ),
    29412945                'apply'                  => __( 'Apply' ),