私は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行目で、 'click .delete-attachment'にバインドされたdeleteAttachment関数があることがわかります。現在の設定で、イメージIDまたは添付オブジェクトを渡してこれにアクセスするにはどうすればよいですか。
やや標準的な(または少なくとも十分に価値のある)答えを試みると、これは子テンプレートディレクトリにあるwpse142997.js
のJavaScriptです。
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 }}&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' );
JavaScriptは私が理解できる限りWP Media Modalの方法に従うことを試みますが、これは部分的なものにすぎません。これはmedia.view.Attachment
を作成し、wp.template
テンプレートを使用します。いくつかの厄介なことがあります - 特に、サイドバーをフレームオブジェクトに遠くまで到達させることは、疑わしいように思われます(そして、たくさんの見回しの後に初めて発見されました)。
destroy
メソッドをattachment
メソッドで呼び出すだけです。これにより、メディアライブラリビューから添付ファイルを削除し、データベース内の添付ファイルとuploadsディレクトリ内のすべてのリンクファイルを削除するためにバックエンドにajax呼び出しを送信します。
IDを取得するために添付ファイルをJSONに変換する必要はありません。バックボーンモデルを直接操作できます。 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 );
Clickイベントのコールバック内でthis
を使えるようにするために $ .proxy を追加しました。