Удалить вложение в модальном окне WP

15

Я пытаюсь создать опцию в окне модального мультимедиа WP для обнаружения дубликатов файлов и удаления более нового файла, если найден более старый дубликат. У меня есть следующий код работает (в сочетании с фильтром 'attachment_fields_to_edit'), чтобы отменить выбор дубликата файла и выбрать оригинальный файл в медиа-модале. Я хотел бы, чтобы, когда пользователь нажимал кнопку, удалял исходный файл (или, по крайней мере, скрывал его в окне библиотеки мультимедиа, чтобы я мог удалить его позже).

( function( $ ) {

    var _AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay;
    wp.media.view.Settings.AttachmentDisplay = _AttachmentDisplay.extend({
        render: function() {
            _AttachmentDisplay.prototype.render.apply(this, arguments);
            currentselection = this.controller.state().get('selection').first().toJSON();
            selection = this.controller.state().get('selection');

            $('button.dmc').on('click', function(e){

                e.preventDefault();

                var id = $(e.currentTarget).data("id");
                if(currentselection.id == id) {

                    currentattachment = wp.media.attachment(id);
                    selection.remove(currentattachment);

                    console.dir(wp.media.view.Attachment);

                    newattachment = wp.media.attachment($(e.currentTarget).data("original"));
                    selection.add(newattachment);

                }
            });
        }
    });

} )( jQuery );

Интерфейс выглядит как прикрепленное изображение.

снимок экрана проверки дубликатов

В файле media-views.js в строке 5873 я вижу, что есть функция deleteAttachment, связанная с «click .delete-attachment». Как я могу получить доступ к этому, учитывая мои текущие настройки, передав идентификатор изображения или объект вложения?

bcorkins
источник
4
Этот вопрос все еще открыт или вы уже нашли ответ?
engelen
@engelen этот вопрос теперь имеет открытую награду. Так что дерзайте :-)
Питер Гусен

Ответы:

5

Попытка несколько канонического (или по крайней мере обильного) ответа, это javascript для wpse142997.jsв дочернем каталоге шаблона:

jQuery( document ).ready(function() {
    ( function( $ ) {
        var media = wp.media,
            l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n,
            attachments = media.model.Attachments.all,
            attachments_uploaded = [];

        if ( typeof wp.Uploaded === 'undefined') return;

        // Keep track of files uploaded.
        wp.Uploader.queue.on( 'add', function ( attachment ) {
            attachments_uploaded.push( attachment );
        });

        // The Uploader (in wp-includes/js/plupload/wp-plupload.js) resets the queue when all uploads are complete.
        wp.Uploader.queue.on( 'reset', function () {
            var idx, uploaded = attachments_uploaded.slice(0); // Clone
            attachments_uploaded = [];
            for ( idx = 0; idx < uploaded.length; idx++ ) {
                if ( uploaded[idx].get('name').match(/-[0-9]+$/) ) {
                    $.post( ajaxurl, {
                            action: 'wpse142997_is_dup',
                            dup_id: uploaded[idx].id,
                            nonce: wpse142997_params.is_dup_nonce
                        }, function( response ) {
                            var original, dup, dup_view, sidebar, selection;
                            if ( response && !response.error && response.original_id && response.dup_id ) {
                                original = attachments.get( response.original_id );
                                dup = attachments.get( response.dup_id );
                                if ( original && dup ) {
                                    dup.set( 'dup_original', original ); // May be ungood - mostly doing it so can use wp.templates.
                                    dup_view = media.view.Attachment.extend({
                                        tagName:   'div',
                                        className: 'attachment-dmc',
                                        template: media.template('attachment-dmc'),
                                        events: {
                                            'click button.dmc': 'removeDupSelectOriginal'
                                        },
                                        initialize: function() {
                                            this.focusManager = new media.view.FocusManager({
                                                el: this.el
                                            });
                                            media.view.Attachment.prototype.initialize.apply( this, arguments );
                                        },
                                        render: function() {
                                            if ( this.get_dup_original() ) {
                                                media.view.Attachment.prototype.render.apply( this, arguments );
                                                this.focusManager.focus();
                                            }
                                            return this;
                                        },
                                        removeDupSelectOriginal: function( event ) {
                                            var dup_original = this.get_dup_original();
                                            event.preventDefault();

                                            if ( dup_original && confirm( l10n.warnDelete ) ) {
                                                this.model.destroy();
                                                this.controller.state().get('selection').add( dup_original );
                                                this.remove();
                                            }
                                        },
                                        get_dup_original: function () {
                                            var dup_original = this.model.get('dup_original');
                                            return dup_original && attachments.get( dup_original.id ) ? dup_original : null;
                                        }
                                    });
                                    // A hacky way to get the sidebar.
                                    sidebar = media.frame.content.view.views.get('.media-frame-content')[0].sidebar;
                                    selection = sidebar.controller.state().get('selection');
                                    // The sidebar boxes get deleted and recreated on each select - hack into this to do the same.
                                    selection.on( 'selection:single', function ( event ) {
                                        if ( selection.single().get('dup_original') ) {
                                            sidebar.set( 'dmc', new dup_view({
                                                controller: sidebar.controller,
                                                model: selection.single(),
                                                priority: 100
                                            }) );
                                        }
                                    } );
                                    selection.on( 'selection:unsingle', function ( event ) {
                                        sidebar.unset('dmc');
                                    } );
                                    // Refire the select as we missed it (could/should just do the view create code here again).
                                    selection.trigger('selection:single');
                                }
                            }
                        }, 'json'
                    );
                }
            }
        });
    } )( jQuery );
});

Это functions.php:

function wpse142997_wp_enqueue_scripts() {
    wp_enqueue_script( 'wpse142997', get_stylesheet_directory_uri() . '/wpse142997.js', array( 'jquery', 'media-views' ), '1.0' );
    $params = array(
        'is_dup_nonce' => wp_create_nonce( 'wpse142997_is_dup_submit_' ),
    );
    wp_localize_script( 'wpse142997', 'wpse142997_params', $params );
    ob_start();
    ?>
<style>
.attachment-dmc { float:left; overflow:hidden; position:relative; }
.attachment-dmc div { background-color:#FFEBE7; border:1px solid #CB9495; border-radius:5px; margin-top:16px; padding:6px; }
.attachment-dmc div h3 { margin-top:0; }
.attachment-dmc div h3 span { background-color:#E70000; border-radius:5px; color:white; margin-top:0; padding:0 6px; }
</style>
    <?php
    wp_add_inline_style( 'media-views', str_replace( array( '<style>', '</style>' ), '', ob_get_clean() ) );
}

function wpse142997_print_media_templates() {
?>
<script type="text/html" id="tmpl-attachment-dmc">
    <# if ( data.dup_original ) { #>
        <div>
            <h3><span><?php _e( 'Duplicate file detected' ); ?></span></h3>
            <p>
                <?php _e( 'This file appears to be a duplicate of <a href="{{ data.dup_original.attributes.editLink }}&amp;image-editor" target="_blank">{{ data.dup_original.attributes.filename }}</a> uploaded on {{ data.dup_original.attributes.dateFormatted }}' ); ?>
            </p>
            <button id="run_dmc" class="dmc" name="dmc"><?php _e( 'Remove duplicate and select original' ); ?></button>
        </div>
    <# } #>
</script>
<?php
}

function wpse142997_is_dup() {
    $ret = array( 'error' => false );

    if ( ! check_ajax_referer( 'wpse142997_is_dup_submit_', 'nonce', false /*die*/ ) ) {
        $ret['error'] = __( 'Permission error' );
    } else {
        $dup_id = isset( $_POST['dup_id'] ) ? $_POST['dup_id'] : '';
        if ( ! $dup_id || ! ( $post = get_post( $dup_id ) ) ) {
            $ret['error'] = __( 'Bad dup_id' );
        } else {
            $post_name = preg_replace( '/-[0-9]+$/', '', $post->post_name ); 
            global $wpdb;
            $sql = $wpdb->prepare( 'SELECT ID FROM ' . $wpdb->posts . ' WHERE'
                . ' post_title = %s AND post_type = %s AND post_mime_type = %s AND post_status = %s AND post_name = %s ORDER BY post_date ASC LIMIT 1',
                $post->post_title, $post->post_type, $post->post_mime_type, $post->post_status, $post_name
            );
            if ( $original_id = $wpdb->get_var( $sql ) ) {
                $ret['original_id'] = $original_id;
                $ret['dup_id'] = $dup_id;
            }
        }
    }

    wp_send_json( $ret );
}

add_action( 'admin_enqueue_scripts', 'wpse142997_wp_enqueue_scripts' );
add_action( 'print_media_templates', 'wpse142997_print_media_templates' );
add_action( 'wp_ajax_wpse142997_is_dup', 'wpse142997_is_dup' );

Яваскрипт пытается следовать WP Media Modal так, насколько я понимаю, что является лишь частичным. Он создает media.view.Attachmentи использует wp.templateшаблон. Есть несколько хакерских битов - получение боковой панели, в частности, через длинный радиус действия в кадре, кажется подозрительным (и было найдено только после большого количества возни).

Бонгер
источник
Спасибо, это определенно то, к чему я стремился. Что касается канонической части, то у меня не так много причин для выбора, и я не мог найти лучший текст самостоятельно, так что это довольно близко. Я посмотрю поближе на следующей неделе.
Николай
Я скопировал код в файл functions.php 2014 года и настроил js, как описано, и до сих пор не вижу раздел с дублирующимися уведомлениями. Какие действия я должен выполнить после того, как код будет на месте, чтобы увидеть это?
KalenGi
Я полагаю, вы загрузили дубликат изображения?! ...
Бонгер
4

Вам просто нужно вызвать destroyметод на attachmentмодели. Это приведет к удалению вложения из представления библиотеки мультимедиа и отправке Ajax-вызова в бэкэнд для удаления вложения в базе данных и всех связанных файлов в каталоге загрузки.

Вам не нужно преобразовывать вложение в JSON, чтобы получить идентификатор: вы можете напрямую манипулировать моделями Backbone. Это selectionколлекция из нескольких приложений.

( function( $ ) {

    var _AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay;
    wp.media.view.Settings.AttachmentDisplay = _AttachmentDisplay.extend({
        render: function() {
            _AttachmentDisplay.prototype.render.apply(this, arguments);

            $('button.dmc').on('click', $.proxy(function(e){

                e.preventDefault();
                selection = this.controller.state().get('selection');
                firstAttachment = selection.first();

                var id = $(e.currentTarget).data("id");
                if(currentselection.id == id) {

                    selection.remove(firstAttachment);
                    firstAttachment.destroy();

                    console.dir(wp.media.view.Attachment);

                    newattachment = wp.media.attachment($(e.currentTarget).data("original"));
                    selection.add(newattachment);

                }
            }, this));
        }
    });

} )( jQuery );

Я также добавил вызов $ .proxy, чтобы можно было использовать его thisв обратном вызове события click.

Фабьен Кватраво
источник
1
Спасибо, выглядит хорошо для меня. Конечно, мои навыки JS и знание этих частей WordPress не так уж велики. Определенно хочу попробовать это на следующей неделе. Еще одна вещь, давайте представим, что я немного знаю о WP, как я могу использовать код, который вы опубликовали?
Николай
Поскольку я не нашел времени, чтобы опробовать ни одно из ваших решений, я дал награду за ответ @bonger - просто потому, что он кажется законченным, еще раз спасибо за ответ.
Николай