記事の一括編集機能を拡張して記事のユーザーを一括変換する(1)
ユーザーの一括変換機能が欲しい
はじめに
MTには記事のユーザー変更機能が有ります。
どういうときに使うかと言うと、
例えば、
あるユーザーが作った記事を他のユーザーが触れないように権限設定しているMT環境があるとします。
この環境で、ユーザーAが作った記事をユーザーBに編集させたい場合が出てきて、ただ実装の都合で記事のエントリーIDを変更できないので、既存の記事のユーザーを変更したい、
というときに必要になったりする機能です。
標準の記事のユーザー変更機能の仕様と課題
この機能、具体的には次の手順で利用します。
- MTのウェブサイト/ブログの管理画面より、「記事の管理」画面を開く。
- 一括編集の対象としたい記事を、記事一覧左のチェックボックスで選択する。
- 記事一覧上部のドロップダウンから「記事の一括編集」を選択し、その横の「Go」ボタンを押す。
- 記事の一括編集の画面に遷移したら、記事一覧の項目「ユーザー」を選択。
- ユーザーを選択するポップアップが出てきたら、そこから変更後のユーザーを選択。
記事の一括編集画面:
ただ、前述の ユーザーA➡B に変更する場合で、ユーザーBに編集させたい記事が数十程あったりすると、いちいち記事1件毎にポップアップを開いてユーザーを指定せねばなりまえん。
もっと言うと、案件によっては千何百と記事のユーザーを変更せねばならない場合もあり、そうなると手間がかかりすぎます。
前置きの説明が長くなりましたが、今回は記事の一括編集画面にユーザーの一括変更機能を追加して、この手間を減らせるようにします。
記事のユーザー一括変更機能の実装
記事の一括編集機能の処理の裏側の動きを調べる
まず、どこをどういじれば良いか分かってないので、標準の記事の一括編集機能における、ユーザー変更の処理の裏側の流れを推測します。
前述の標準機能によるユーザー変更手順の内、記事の一括編集画面に遷移してからの辺りをもう少し細かく見てみます。
- 項目「ユーザー」にあるユーザー名のリンクを押す。
- ユーザー選択のポップアップが出る。
- ユーザーを選択し「OK」ボタンを押すと、記事の一括編集画面にフォーカスが戻り、変更対象の記事の項目「ユーザー」に、変更後のユーザー名が反映される
(「OK」ボタンを押した際は、待ち時間も無くほぼ即時変更後のユーザー名が反映される為、JSの処理のみが行われていると思われる) - 「保存」ボタンを押すと、設定した内容が反映される。
(記事の一括編集画面の記事一覧部分は、formタグで囲われており、「保存」ボタンを押すと、MTのあるサーバー側に設定内容が送信され、MTがその内容をDBに反映させる仕組み、と推測される)
ここで「OK」ボタンを押した後の処理に注目します。
どうも一括編集の機能におけるユーザーの変更処理は、JSでフォーム内のinputタグのvalue属性を変更し、それをformタグの機能でMT側に送る事で実現されているようです。
この仮説の信憑性を確かめる為、今度はユーザーを変更する前と後での、記事の一括編集画面のHTMLソースの差分を見てみます。
※HTMLソースは、ブラウザの開発者ツールから取得します。右クリックからのHTMLソース取得だと、JSによるHTMLソースの変化を見れないのでそうします。
すると、記事一覧の変更した記事の項目「ユーザー」の箇所のソース(下記ソース)について、差分がある事が分かりました。
<td class="col author"> <input type="hidden" name="author_id_54" value="4" id="entry_author_id_54" class="first-child hidden"> <a href="/mtos5_pub/basectl.cgi?__mode=dialog_select_author&blog_id=2&multi=0&entry_type=entry&idfield=entry_author_id_54&namefield=entry_author_name_54" class="mt-open-dialog last-child"><span id="entry_author_name_54" class="first-child last-child">test_user2 (4)</span></a> </td>
具体的には、前述ソースにおいて、ユーザー変更前と後で、次の値が書き変わっています。
- inputタグのvalue属性(ユーザーIDが入る)
- spanタグでマークアップされたユーザー名の文字列
なので、ユーザー一括変更の機能実装は、直接的には、MT本体側のperlコードをいじったりプラグインからコールバックを呼び出すような複雑な処理は必要なく、ユーザー情報に対応するinputタグのvalue属性をJSで一括変更すれば実現できそうです。
これを踏まえて、ユーザー一括変更機能の実装方法を考えます。
実装方法を考える
後は何処にUIとJSのコードを書くか、です。
記事の一括編集画面のUIを出力しているのは、次のテンプレートファイルです。
[MT本体のルートディレクトリ]/tmpl/cms/edit_entry_batch.tmpl
このファイルの、43行あたりにコードを書き加えます。
(変更前)
<mtapp:listing hide_pager="$hide_pager"> <mt:if __first__> <mt:setvarblock name="table_header"> <tr> <th class="col head status"><span class="col-label"><__trans phrase="Status"></span></th> <th class="col head title primary"><span class="col-label"><__trans phrase="Title"></span></th> <th class="col head category"><span class="col-label"><mt:if name="object_type" eq="page"><__trans phrase="Folder"><mt:else><__trans phrase="Category"></mt:if></span></th> <th class="col head author"><span class="col-label"><__trans phrase="Author"></span></th> <th class="col head datetime"><span class="col-label"><__trans phrase="Published Date"></span></th> <th class="col head datetime"><span class="col-label"><__trans phrase="Date Modified"></span></th> </tr> </mt:setvarblock> <thead> <mt:var name="table_header"> </thead> <tfoot> <mt:var name="table_header"> </tfoot> <tbody> </mt:if>
(変更後)
<mt:if __first__> <mt:setvarblock name="table_header"> <tr> <th class="col head status"><span class="col-label"><__trans phrase="Status"></span></th> <th class="col head title primary"><span class="col-label"><__trans phrase="Title"></span></th> <th class="col head category"><span class="col-label"><mt:if name="object_type" eq="page"><__trans phrase="Folder"><mt:else><__trans phrase="Category"></mt:if></span></th> <th class="col head author"><span class="col-label"><__trans phrase="Author"></span></th> <th class="col head datetime"><span class="col-label"><__trans phrase="Published Date"></span></th> <th class="col head datetime"><span class="col-label"><__trans phrase="Date Modified"></span></th> </tr> </mt:setvarblock> <thead> <mt:var name="table_header"> <mt:ignore>追記ここから</mt:ignore> <script type="text/javascript"> function KM_ReplaceAllAuther(){ var km_auther_id = jQuery("#KmControlSelectAuther").val(); var km_auther_basename = jQuery( "#KmControlSelectAuther option[value='" + km_auther_id + "']" ).text(); jQuery("#entry-listing-table td.col.author input").each(function(i, elem){ elem.value = km_auther_id; }); jQuery("#entry-listing-table td.col.author span").each(function(i, elem){ elem.innerHTML = km_auther_basename + ' (' + km_auther_id + ')'; }); } </script> <select id="KmControlSelectAuther"> <option value="0" class="first-child">アクション...</option> <option value="3">test_user1</option> <option value="4">test_user2</option> </select> <button type="button" onclick='KM_ReplaceAllAuther();'>ユーザーを一括変更する</button> <mt:ignore>追記ここまで</mt:ignore> </thead> <tfoot> <mt:var name="table_header"> </tfoot> <tbody> </mt:if>
具体的には、HTMLソース上における記事一覧上部に、次のコードを追加しています。
- ユーザー選択用のドロップダウン
- 「ユーザーを一括変更する」ボタン。
- 「ユーザーを一括変更する」ボタンが押された際に、記事一覧の全記事の項目「ユーザー」に該当する箇所(inputのvalueおよびspanタグに囲まれた文字列)を、指定したユーザーのものに書き換える為のJSコード。
(実装後の記事の一括編集画面の見た目)
これで、次の手順でユーザーの一括設定が可能になります。
- ドロップダウン「アクション」から、ユーザーを選択。
- 「ユーザーを一括変更する」ボタンを押して、指定したユーザーを編集対象の全記事に設定する。
- 「保存」ボタンで設定反映。
とりあえず実装はしてみたが、、、
殆どの方は気づかれていると思いますが、先のedit_entry_batch.tmplにて追記している「ユーザーを選択する」ドロップダウンについて、選択肢となるoptionタグの部分はMTからユーザーの一覧を採るような処理はしておらず、直書きで設定しています。
次の方法で取れないか試したのですが、どうもうまく行きません。
- mtAutorsタグの利用 →管理画面のテンプレートでは動作しない模様。
- MTAppjQueryの機能で取得 →現時点でそんな都合の良い機能は無い模様。
という事で、この部分は次回に持ち越しですヽ(・、 .)ノ