WordPressでメディアのアップロード時にテキスト欄やラジオボタンを追加する:メモ

悩み
悩み

検索でそれなりに情報は出てくるのに、微妙に実現したいこと少しだけ離れていてなかなか進みませんでした。

調べて試して形にしたのでメモとして残しますが、今回は特に参照したサイトが複数あったので、後ほど振り返えれるように列記しています。

なお、自分自身のメモ記事でも注意せねばと強く思いましたが、入力部分のコードだけ書いて出力部分を省略されると非常に難儀しますね。

構築環境
WordPress4.5.3

実現したいこと

実現したいことは以下の通り。WordPressのバージョンは4.5.3です。

  • 投稿画面から画像を挿入する際、img要素に任意で特定のクラスを付ける
  • 任意のクラスはメディアのアップロードに都度設定
  • カスタムフィールドを利用

概要メモ

今回の作業大別すると以下の3つでした。

  1. カスタムフィールドをアップロード画面に追加
  2. 投稿画面からの画像挿入時にクラスを追加
  3. 上記1と2を関連づける

1と2を個別に実装するだけならそれほど大きな問題は無かったのですが、3が絡むとなかなか上手くいかず。

あとはカスタムフィールドの値をimgのクラスに入れるだけというところで、後戻りや調べ直しが必要になりました..。

ポイント1: attachment_fields_to_edit

メディアの部分に追加するフックは、attachment_fields_to_editでした。

これが必要だということはすんなりわかりましたが、今まで使ったことがなかったため$form_fieldsの配列やそこにカスタムフィールドを入れ込む構造がすんなり理解できませんでした。

特に、attachment_fields_to_editで使われる引数の$form_fieldsがよく分かりませんでした。

WordPress.orgの上記ページでは、引数の説明として以下のように書かれています。

$form_fields
(array) An array of attachment form fields.

これでも実態がよくわからなかったため、Sourceに示されたmedia.phpの中身を見ましたが、そこでもよくわからず。

その後調べて情報を見つけましたが、この件はやや長くなるので別ページに記載します。

ポイント2: get_image_tag_class

前項の単純な方法に絡みますが、カスタムフィールドの値を取り込んで出力するフックとしては以下の2つが考えられました。

image_send_to_editor
get_image_tag_class

調べてみると以下のような違いがあることが分かりました。

  • 画像挿入時に出力されるコード全体を触る場合にはimage_send_to_editorを使う
  • img要素の属性を触る場合にはget_image_tag_classを使う

image_send_to_editorを使う方法は出力に大きな影響があり、デフォルトの構造を壊す可能性もあって、今回の目的を大きく越えるフックでした。
また、参考にしたサイトでは正規表現を用いて Attachment ID の値を取り出す必要があると書かれていました。

対して、get_image_tag_classimgの属性だけを変更するため、対象が限定的ですから必要最小限の処理が可能で、今回の目的に合致しました。
引数の$idに既にAttachment IDが入っていますので、正規表現なしで単に$idで値が取れるのでシンプルに使えました。

get_image_tag_classから具体的な内容を引用します。

Parameters #Parameters
$class
(string) CSS class name or space-separated list of classes.
$id
(int) Attachment ID.
$align
(string) Part of the class name for aligning the image.
$size
(string|array) Size of image. Image size or array of width and height values (in that order). Default ‘medium’.

$idは除いて、$class$align$sizeが対象となります。

サンプルコード

2つのサンプルコードを記載します。

textを追加したタイプ

カスタムフィールドにテキストを追加するタイプです。


//カスタムフィールドの設置
add_filter("attachment_fields_to_edit", "add_image_myclass", 10, 2);
function add_image_myclass($form_fields, $post) {
  $form_fields["myclass"] = array(
    "label" => "追加クラス名",
    "input" => "text",
    "value" => get_post_meta($post->ID, "_myclass", true),
  );
  return $form_fields;
}
//カスタムフィールドの保存
add_filter("attachment_fields_to_save", "save_image_myclass", 10 , 2);
function save_image_myclass($post, $attachment) {
  if (isset($attachment['myclass']))
    update_post_meta($post['ID'], '_myclass', $attachment['myclass']);
  return $post;
}
//カスタムフィールドの出力
add_filter('get_image_tag_class', 'insert_image_myclass', 10,2);
function insert_image_myclass($class,$id) {
  $myclass ='';
  $myclass = get_post_meta($id, '_myclass', true);
  if(!empty($myclass)){
    $class .= ' '.esc_html($myclass);
  }
  return $class;
}

上記コードで任意のクラス名が出力できます。

ラジオボタンを追加したタイプ

ラジオボタンを用いてクラスの付与を行います。


//カスタムフィールドの設置
add_filter("attachment_fields_to_edit", "add_image_myclass", 10, 2);
function add_image_myclass($form_fields, $post) {
  //ラジオボタン表示時点の状態をチェック
  $selected = get_post_meta( $post->ID, 'be_image_myclass', true );
  if(!$selected || $selected == 'myclass-off'){
  //「装飾なし」か未選択ならのoffに設定
    $checked_off = " checked='checked'";
  } else {
  //「装飾あり」ならのonに設定
    $checked_on = " checked='checked'";
  }
  //ラジオボタンのhtmlを設定
  $html = "<div class='images-myclass-option'>";
  $html .= "<input type='radio' name='attachments[$post->ID][be_image_myclass]' id='images-myclass-option-1' value='myclass-on'$checked_on />";
  $html .= "<label for='images-myclass-option-1'>装飾あり</label>";
  $html .= "<input type='radio' name='attachments[$post->ID][be_image_myclass]' id='images-myclass-option-2' value='checked_off'$checked_off />";
  $html .= "<label for='images-myclass-option-2'>装飾なし</label>";
  $html .= '</div>';
 //ラジオボタンのhtmlを出力
  $form_fields["myclass"] = array(
    "label" => "装飾の有無",
    'input' => 'html',
    'html'  => $html,
  );
  return $form_fields;
}
//カスタムフィールドの保存
add_filter("attachment_fields_to_save", "save_image_myclass", 10 , 2);
function save_image_myclass($post, $attachment) {
  if (isset($attachment['be_image_myclass']))
    update_post_meta($post['ID'], 'be_image_myclass', $attachment['be_image_myclass']);
  return $post;
}
//カスタムフィールドの出力
add_filter('get_image_tag_class', 'insert_image_myclass', 10,2);
function insert_image_myclass($class,$id) {
  //カスタムフィールドに値があるかどうかをチェック
  $myclass ='';
  $myclass = get_post_meta($id, 'be_image_myclass', true);
  if(!empty($myclass)){
    $class .= ' '.$myclass;
  } else {
    $class .= ' myclass-off';
  }
  return $class;
}

見苦しい部分もありますが、動作はすると思います。

「装飾あり」を選択するとmyclass-onクラスが付与され、「装飾無し」を選択するか未選択の場合にはmyclass-offが出力されます。

aタグにもクラスを付与

ついでに、aタグにもクラスを設定することが可能です。

上記の情報を参考に、といいますかほぼそのままです。


add_filter( 'image_send_to_editor', 'add_class_wpimage_link' );
function add_class_wpimage_link( $html ) {
  $class = 'wrap_wpimage_link';
  return str_replace( '<a ', '<a class="'. $class. '" ', $html );
}

参考情報

カスタムの内容としては割とありそうな感じでしたが、実際にも情報はわりと見つかりました。

後で元情報に当たれるようにメモがてら列記します。

追加メモ

補足的なメモです。

メディアアップローダーを動かすためのphp

メディアアップローダーを動かすためのphpファイルは以下のファイルです。

  • media.php

オプションの表示

記事内容とは直接関係ありませんが、調査の過程で知ったので補足事項として。

まず使うことはないと思いますが、以下の方法で管理画面から各種のオプションの値の確認と変更が可能です。

  • ドメインにwp-admin/options.phpを付ける

管理画面から設定可能な各種項目が並んでいるようで、一覧でそれらの設定内容を確認する際は使えるかもしれません。

結び

知れば便利なテンプレートタグや関数はまだまだあるのだと実感します。

1人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。