WordPress メタボックスでファイルアップロード
概要
「WordPress メタボックス追加サンプルコード」の続き。記事編集ページに、メタボックスでファイルアップロード機能を追加する処理の説明。
サンプルコードは以下。
https://github.com/kztomita/wordpress-plugin-sample-metabox
全体の説明は「WordPress メタボックス追加サンプルコード」を参照。
ファイルアップロード処理に関する説明
sample-metabox-admin-file.phpの説明。
sample-metabox-admin-file.phpは図1に示すメタボックスを追加する。本ファイルは、<input type="file" />を使ったファイルのアップロードを行う。アップロードしたファイルはメディアライブラリに登録せずに、記事編集ページのみで管理を行う。ファイルを再アップロードした場合は、旧ファイルを削除することで、ファイルの差し替えを行い、記事を削除した場合は、アップロード済みのファイルを削除する。
処理はsample-metabox-admin-checkbox.phpと同じく、メタボックスの表示処理と保存処理の二つに分かれる。
図1 sample-metabox-admin-file.phpが追加するメタボックス
メタボックス表示処理
function sample_metabox_add_file() { wp_nonce_field('sample_metabox', 'sample_metabox_file_nonce'); $id = get_the_ID(); $post_meta = get_post_meta($id, SAMPLE_METABOX_METAKEY_FILE, true); if ($post_meta) { echo '<p><a href="'.$post_meta['url'].'" target="_blank">'.$post_meta['url'].'</a></p>'; } $name = SAMPLE_METABOX_NAME_FILE; echo <<<END_OF_TEXT <input type="file" name="{$name}" id="{$name}" value="" /> END_OF_TEXT; if ($post_meta) { echo <<<END_OF_TEXT <label><input type="checkbox" name="{$name}_delete" id="{$name}_delete" value="1" />ファイルを削除</label> END_OF_TEXT; } } function sample_metabox_add_meta_boxes_file() { add_meta_box('id_sample_metabox_file', 'ファイルアップロード(PDF)', 'sample_metabox_add_file', 'post', 'normal', 'high'); } add_action('add_meta_boxes', 'sample_metabox_add_meta_boxes_file'); /* ファイルアップロードに必要 */ function sample_metabox_edit_form_tag() { echo ' enctype="multipart/form-data"'; } add_action('post_edit_form_tag', 'sample_metabox_edit_form_tag');
メタボックスの表示処理はチェックボックスのものとほぼ同じ。一点注意が必要なのは、<input type="file" />を使うため、formタグにenctype="multipart/form-data"を指定する必要がある。これは、post_edit_form_tagアクションで行っている。
ファイルアップロード処理
function sample_metabox_save_file($post_id) { if (!isset($_POST['sample_metabox_file_nonce'])) { return; } if (!wp_verify_nonce($_POST['sample_metabox_file_nonce'], 'sample_metabox')) { return; } if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } /* 権限チェック */ if (isset($_POST['post_type']) && 'page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) { return; } } else { if (!current_user_can('edit_post', $post_id)) { return; } } /* * ファイル削除を行うかチェック */ $post_meta = get_post_meta($post_id, SAMPLE_METABOX_METAKEY_FILE, true); if ($post_meta && $_POST[SAMPLE_METABOX_NAME_FILE.'_delete']) { @unlink($post_meta['file']); delete_post_meta($post_id, SAMPLE_METABOX_METAKEY_FILE); return; /* 終了。アップロードは行わない。 */ } /* * アップロードされたファイルのチェック */ if(empty($_FILES[SAMPLE_METABOX_NAME_FILE]['name'])) { /* ファイルなし */ return; } $file = $_FILES[SAMPLE_METABOX_NAME_FILE]; $file_type = wp_check_filetype($file['name']); if ($file_type['ext'] != 'pdf') { wp_die('Unsupported file type. (Supported file type: .pdf)'); } /* ファイル保存 */ /* 旧ファイルがあれば削除 */ if ($post_meta) { @unlink($post_meta['file']); } /* * アップロードフォルダにファイル保存。 * 同名ファイルあれば、リネームされた名前が使われるので、 * 上書きされる心配はない。 * sanitize_file_name()も行われる。 */ if (0) { $upload = wp_upload_bits($file['name'], null, file_get_contents($file['tmp_name'])); } else { $overrides = array('test_form' => false); $upload = wp_handle_upload($file, $overrides); } if(isset($upload['error']) && $upload['error']) { wp_die('Upload error : '.$upload['error']); } $post_meta = array('file' => $upload['file'], 'url' => $upload['url'], 'type' => $upload['type'], ); update_post_meta($post_id, SAMPLE_METABOX_METAKEY_FILE, $post_meta); } /* * save_post_{$post_type}のactionを使用 * 全post_typeを対象にするなら、save_post actionを使用 */ add_action('save_post_post', 'sample_metabox_save_file');
保存処理の前半では、チェックボックスの時と同じく、nonce、自動保存、権限のチェックを行う。その後、ここではPDFファイルのアップロードに限定しているため、wp_check_filetype()で拡張子をチェックし、アップロードされたファイルをuploadディレクトリに移動する。
ファイルをuploadディレクトリに移動する際は、wp_handle_upload()を使う。この関数はファイル名のチェック等を行った後、move_uploaded_file()でファイルをuploadディレクトリ以下に移動してくれる。同名ファイルが既にあれば、foo2.pngのような別名が使われるので、上書きされる心配はない。また、sanitize_file_name()も内部で行われる。
wp_handle_upload()ではなく、wp_upload_bits()を使っても問題ないが、推奨はwp_handle_upload()のようだ。
ファイルを移動後は、ファイルの情報をpost_metaに保存する。
記事削除時の処理
function sample_metabox_before_delete_post($post_id) { global $post_type; if ($post_type != 'post') return; /* ファイルの削除 */ $post_meta = get_post_meta($post_id, SAMPLE_METABOX_METAKEY_FILE, true); if ($post_meta) { @unlink($post_meta['file']); } /* post_meta情報自体はシステムの方で削除される */ } add_action('before_delete_post', 'sample_metabox_before_delete_post');
アップロードしたファイルはメディアライブラリに登録していないため、記事を削除(ゴミ箱から削除)すると、アップロード済みのファイルが宙ぶらりんになってしまう。このため、記事削除時に対象記事のアップロードファイルも削除するようにしている。
メディアライブラリを使ったアップロードを行うメタボックスの説明
「WordPress メタボックスでメディアライブラリ呼出し」へつづく。