管理画面にメディアアップローダを組み込む【改訂版】

以前、管理画面から画像をアップロードするコードをただ載せただけで、このブログにしては反響があった。

しかしこのコードは旧版のメディアアップローダーを利用したもので、機能するものの最新のWPと統一感が取れていない。

そこで、例によって別の記事の受け売りだが、最新版のアップローダーに対応したコードを紹介しようと思う。

準備作業:オプションページを作る

ここはどんな管理ページでも同じだ。例えば、以下のようなコードで管理ページを作成

add_action( 'admin_menu', 'register_media_selector_settings_page' );

function register_media_selector_settings_page() {
	add_submenu_page( 'options-general.php', 'Media Selector', 'Media Selector', 'manage_options', 'media-selector', 'media_selector_settings_page_callback' );
}

フォームを作る

既存のフォームに組み込むのなら不要。
また、enctype=”multipart/form-data”などは必要ない。というのは、画像のアップロードはこのフォームを通して行われるわけではなく、WP内部のアップローダを通して行われるからだ。

function media_selector_settings_page_callback() { ?>
<form method="post">
<div class="image-preview-wrapper">
<img id="image-preview" src="<?php echo wp_get_attachment_url( get_option("image_attachment_id"))?>" height="100">
</div>
<input id="upload_image_button" class="button" type="button" value="<?php _e( 'Upload image' ); ?>">
<input id="image_attachment_id" name="image_attachment_id" type="hidden" value="<?php echo get_option("image_attachment_id"))?> > 
<input class="button-primary" name="submit_image_selector" type="submit" value="Save"></div>
</form>
<?php
}

必要なjsなどをインクルード

ここが実にあっけない。
wp_enqueue_media()という関数一発で、必要なファイルをインクルードしてくれる。WPも便利になったものだ。
このコマンド内で何をしているか気になる人はここを見て欲しい。実に周到に準備をしている事が分かる。

結果、コードはこうなる。

function media_selector_settings_page_callback() {

	wp_enqueue_media();
  
//略
	?>
}

アップローダと仲だちするスクリプトを読み込む

ここが一番要の部分だ。
実は今の時点ではあまりコードを読み解けていない。ただ、アップローダ内からIDをかっさらって来る部分は旧版と同じ仕組みだ。

add_action( 'admin_footer', 'media_selector_print_scripts' );

function media_selector_print_scripts() {

	$my_saved_attachment_post_id = get_option( 'media_selector_attachment_id', 0 );

	?>
		jQuery( document ).ready( function( $ ) {
			// Uploading files
			var file_frame;
			var wp_media_post_id = wp.media.model.settings.post.id; // Store the old id
			var set_to_post_id = <?php echo $my_saved_attachment_post_id; ?>; // Set this
			jQuery('#upload_image_button').on('click', function( event ){
				event.preventDefault();
				// If the media frame already exists, reopen it.
				if ( file_frame ) {
					// Set the post ID to what we want
					file_frame.uploader.uploader.param( 'post_id', set_to_post_id );
					// Open frame
					file_frame.open();
					return;
				} else {
					// Set the wp.media post id so the uploader grabs the ID we want when initialised
					wp.media.model.settings.post.id = set_to_post_id;
				}
				// Create the media frame.
				file_frame = wp.media.frames.file_frame = wp.media({
					title: 'Select a image to upload',
					button: {
						text: 'Use this image',
					},
					multiple: false	// Set to true to allow multiple files to be selected
				});
				// When an image is selected, run a callback.
				file_frame.on( 'select', function() {
					// We set multiple to false so only get one image from the uploader
					attachment = file_frame.state().get('selection').first().toJSON();
					// Do something with attachment.id and/or attachment.url here
					$( '#image-preview' ).attr( 'src', attachment.url ).css( 'width', 'auto' );
					$( '#image_attachment_id' ).val( attachment.id );
					// Restore the main post ID
					wp.media.model.settings.post.id = wp_media_post_id;
				});
					// Finally, open the modal
					file_frame.open();
			});
			// Restore the main ID when the add media button is pressed
			jQuery( 'a.add_media' ).on( 'click', function() {
				wp.media.model.settings.post.id = wp_media_post_id;
			});
		});
	

読み解くにはアップローダjsの仕様を理解する必要がありそうだ。それにしても
// Finally, open the modal
file_frame.open();
と最後にモーダルを開いているのはなぜだろう??

画像IDを保存する部分を作成

フォームの目的はアップロードされた画像のID(もしくはURL)を保存する事なので、これを保存・表示する部分が必要になる。
普通のhiddenフィールドだ。

フォームの部分はこうなる。

function media_selector_settings_page_callback() {

	// Save attachment ID
	if ( isset( $_POST['submit_image_selector'] ) &amp;&amp; isset( $_POST['image_attachment_id'] ) ) :
		update_option( 'media_selector_attachment_id', absint( $_POST['image_attachment_id'] ) );
	endif;

	wp_enqueue_media();

	?>

<form method="post">
<div class="image-preview-wrapper">
<img id="image-preview" src="<?php echo wp_get_attachment_url( get_option( " height="100">
<input id="upload_image_button" class="button" type="button" value="<?php _e( 'Upload image' ); ?>">
<input id="image_attachment_id" name="image_attachment_id" type="hidden" value="<?php echo get_option(image_attachment_id);?>">
<input class="button-primary" name="submit_image_selector" type="submit" value="Save"></div>
</form>

<?
}

これで出来上がりだ。

これで上手く行かなかったら、原文を読みに行った方が良いかも知れない。

それでも分からなかったら、さらにその原文へ・・・という風に辿ってみましょう。

追記・備考

このサンプルは「シングル・インスタンス」専用です。つまり1ページに1個しか置けません。
マルチにするには幾つかの点を改造する必要があります。
それほど難しくは無いですが、要点は

  • それぞれのオプション名をユニークにする(連番等)
  • フォームのIDの部分はclassに変え、スクリプト中もそれに合わせる
  • スクリプトの改造:押されたボタンthisを基準に充填するフォームを指定。jQueryを知っていれば誰でも出来ます

コメント

タイトルとURLをコピーしました