2007年9月アーカイブ

テンプレートのところはツッコミ来るかなぁと思っていましたがまぁいいや! って書いたらやっぱり来ましたね。(o)さんは絶対にそこんとこ見逃しちゃぁくれません!

あと実験に関して付け加えると、やや公正さに欠けると思います。2.が「ブログ記事のメタデータ」モジュールのみ外した状態になっているのは比較上問題があります。利用するテンプレートの個数が異なりますから。それなら最初からflatteningしたテンプレートを使って比較すべきです。

たしかにモジュール読み込む時間分不公平でしたごめんなさい。

引き続きブログ(サイト)内検索を考える

「検索」についてはあれこれこれまでもやっていて、このブログにはHyper Estraier入れて、エントリーの保存時にインデックスを更新するプラグインを書いて利用してるので(出力の方はPHPにしてて起動のストレスもあんまりなくて)速度的には問題ないと感じてるのですが、皆がみんな導入出来るわけでもないわけで。

今週2本検索プログラム書いてみました。まだまだチューニングできるかと思うので もうちょっと何とかなったら公開しますね。

結局、検索に対する要求をmt-searchが満たせない(とWeb屋としての僕が思う)のは、

  • 表示件数はともかく、何件マッチしたかが知りたい
  • せめてページ送りができると嬉しい
  • 検索語がハイライトとかできるといいな
  • 検索結果の表示順にキーワードの出現頻度とかを考慮して欲しい
  • HTMLタグまで検索に含まれるのはどうにかして欲しい
  • 1ページにある程度の件数は欲しい

* 「結局ブログ内検索はどうすればいいのか?」Googleを使えってのはとりあえず考えないこと前提で (話がそれまくるので) 。

最後の話については、例えば(僕の知っている)視覚障害者の人は「ページ内検索」を良く使います。(cmd(ctrl)+F)で検索結果ページに対してページ内検索をかけて欲しい情報を探して移動するような使い方。

こういうことを考えると、ページ送りがあるにしても1ページにある程度の件数が欲しくなります。マッチするページが多ければ多い程。

で、もちろんmt-searchはタグ検索とか色々な役割を担っていてこれはこれで必要な機能を実現するために必要なものですが、(o)さんもご指摘の通り相変わらずふざけるなってくらい遅いですということなので、検索については案件毎に作ったりしていたのです。

で、今回MT::Objectのサブクラスを作ってテーブルを拡張してたりすると、そのテーブルがmt-serarchでは反映されてくれないということで(当たり前なんですけど、毎回オリジナル検索作るのも馬鹿げてると思ったので)汎用的なのを作ってみました。

結局、(MTにおける)サイト内検索の速度ってのは

  1. PerlCGIの起動の速度の問題
  2. 純粋な検索速度の問題
  3. テンプレートの再構築速度の問題
  4. データの転送とブラウザのレンダリング速度の問題

の4つの要素が絡むのかと思うわけですね。

1つめはFastCGI(mod_perl)かPHPを使うことで改善されます。問題は2番目と3番目かな。あと4番目もMT4のデフォルトテンプレートだと「ブログ記事のメタ情報」以前に、エントリーの本文とか(貼付けてある画像も表示されるし)これ全て検索結果に必要? って思うものが含まれています。もちろん、タグでの絞り込みとかにはいいんでしょうが。

さて、今回は2つめの件、つまり純粋に高速検索を実現するにはどうするかを考えてみました。

方法1. mt-searchと同じくループで回してマッチング

検索すべき文字列を一つのテーブルに放り込む。その際にHTMLタグは削除してしまう。但し画像のALT属性とかは検索対象にするようなフィルターを噛ましてから放り込む。

後は普通にループでマッチングを調べる。但し正規表現でなくindex関数を使って文字列が含まれるかどうか調べる。

最大検索数は設けるものの、その件数に達するまではループさせてページ送りを実装する。ここが一つの問題で、マッチした件数を調べるためにループを継続しないといけないのです。なぜなら「この文字列を含むレコード数」を簡単に調べる方法が現状のMTでは無いから。結局MySQLとかでLIKE検索した方が圧倒的に速いのです。

ただ、経験上ループ自体は(対象エントリーが数百であれば)そんなに時間かからないと感じているので、まぁやってみようかと。

あと、高速化のために、テーブルには表示用のデータ(ページの概要, メタデータとか)を一緒に保存しているので、ループでマッチすると同時に検索結果用のデータも取得できる。

体感速度は結構速いです。何よりも、環境を選ばないのがメリット。MTが動いていれば動作します。

方法2. 形態素解析で分かち書きして検索インデックスを作る

テーブルに放り込むところは方法1をベースにして、検索対象のテキストを mecab で分ち書きして記号や助詞助動詞、非自立とか不要そうなものを除いてデータベースに入れる。テーブルには単語とその出現回数、エントリーのID等や更新日(無駄なインデクシングを避けるため)を入れておく。

例えばMT4インストール後に自動的にできるエントリーを分かち書きして不要なものを除いた結果はこんな感じ。

Movable Type 4 0 ようこそ この ブログ 記事 Movable Type 4 インストール 完了 時 システム 自動的 作成 ブログ 記事 新しく MT 4 管理 画面 早速 ブログ 更新

インデクシングする時は英文字は小文字にする(MySQL環境だとMTのPerl APIから検索する時に区別してくれないようなので、数があわなくなる)。

各ワードと出現回数はこんな感じになる。

出現回数
mt1
記事3
システム2
インストール2
ブログ4
作成1
完了2
画面1
type2
自動的1
movable2
更新1
管理1
新しく1
この2
早速1
43

これに、更新日とかオブジェクト(エントリーのIDとか)を一緒に保存。こうしておけばマッチするエントリーの数は


my $match = Itasenpara::Itasenpara->count( { blog_id => $blog_id ,
                                             keyword => $query } );

で得られるし、トータル数を得ておいてからオフセットとリミットを指定して検索できるから必要な数だけロードしてあとはページ送りを実装してやることができるよね。

* Object名はItasenpara(イタセンパラ) にした! Namazuにインスパイアされて!?


my @entries = MT::Entry->load( blog_id => $blog_id, {
    'join' => [ 'Itasenpara::Itasenpara', 'object_id',
    { keyword => $query },
    { 'sort' => 'word_count',
    direction => 'descend',
    unique => 1,
    offset => $offset,
    limit => $limit, } ]
});

マッチした数等を表示

ページ送りの実装

もちろんいいことばかりじゃないけど、メリットは単語の出現回数順に表示できるところと高速なところ。デメリットは再構築に時間がかかるところ。但し一回全再構築してしまえば更新日付をチェックしてインデクシング不要ならスキップするようにしたのでまぁ高速な検索のトレードオフというか、今気づいたけどそれこそインデクシングはバックグラウンド処理ですればいいんだ、そうだよね、きっと。

あとは複数ワードのAND検索とかOR検索だけど、素直にSQL書いた方が速いような気がしてます。ってか、もうちょっとスピード出るかと思った...

mecabをインストールする時点でHyper Estraierのパターンと同じく導入に条件が入る。だからこそ「方法1. mt-searchと同じくループで回してマッチング」のような方法もあわせて選択できるようにしておくのがいいかな、と。Namazuだったらインストール済みサーバーも多いんだけど、UTFのことがあってインデクシング用プラグインとか書く気が起こらないんだよなぁ。


追記: 結論としては、2の方法でインデックスを作成しておいてPHP/Perl(FastCGI)で検索、という方向が良いように思う(分かち書きが無理な場合は1の方法+PHP検索)。っていうかさっきはじめてPHP対応のMTプラグイン書いてみて、何とかいけそうだなと思ったので。

サーバーへの負荷もさるところながら、「利用する人のストレスのことも考えると検索結果が表示されるまでにどのくらいなら待てるものなのだろう」などと考えながらMTの検索を独自に実装しようと思って昨日のエントリー (MTからデータベースへのクエリの発行回数を減らす (mt-search.cgiを例にとって)。) を書いていたのだが、昨日のエントリーではMySQLのログ見ただけだったので実際に検証してみた((o)さんからツッコミもあったことだし)。えーっと、ちなみに数字は「再構築」に要した時間。検索に要した時間ではないので。

このブログのエントリーをエクスポートして、ほぼデフォルト状態のMT4にインポート。

Time::Hiresモジュールをインストール、ぴろりさんのMTStopWatchを入れてキーワード「MT」で検索して計測。

ちなみにキーワード「MT」だと約380件のエントリーのうち、(MaxResultsを設定しない場合) 100件強がマッチする。

MaxResultsを20, 40, 80にそれぞれ設定して以下の3タイプのテンプレートで検索実行

  1. 昨日のエントリーで紹介した、タイトル+リンクのシンプルな検索結果。
  2. 「ブログ記事のメタデータ」モジュールのみ外した状態。つまりコメント数やトラックバック数だけが出ない。あとはデフォルトテンプレートのまま。
  3. デフォルトの「検索結果」テンプレートそのまま。

10回実行して平均値を算出。単位は「秒」。数字自体は環境に大きく依存するので違い (差) に着目。

MaxResults 20
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1150.1480.418
20.1070.1560.353
30.1090.1530.351
40.1080.1490.352
50.1120.1460.361
60.1190.1570.36
70.1090.1560.352
80.1150.1550.361
90.1120.1580.355
100.1060.1580.362
平均0.1110.1540.363

MaxResults 40
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1270.2120.660
20.1260.2010.601
30.1320.2040.626
40.1310.2060.617
50.1280.2000.609
60.1320.2070.607
70.1270.2000.605
80.1270.2010.610
90.1310.1980.610
100.1260.2100.620
平均0.1290.2040.617

MaxResult 80
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1770.3171.276
20.1670.3851.145
30.1870.3191.143
40.1730.3191.412
50.1750.3191.266
60.1790.3221.148
70.1690.3331.139
80.1660.3181.135
90.1660.3261.142
100.1690.3311.142
平均0.1730.3291.195

もちろん処理全体に占める「再構築」時間の比率にもよるだろうが、この位差が出るのであれば「下手な最適化」でもないと思うけどなぁ。もちろん検索結果の上限値を設定すること自体に異論はないですけど。

*一応汎用的で高速な検索については現在作成中。

SQLを意識せずにプログラミングできるのが僕がMTを好きな理由の一つであるけれども。

たまにはMTがどんなクエリを発行しているか見てみよう。

MySQLを起動、mt-search.cgiで検索して、MySQLのログを覗いてみる。行数は起動の際のログも含めた行数。

MySQLのログはMAMPの場合、/Applications/MAMP/bin/startMysql.sh に


--log=/Applications/MAMP/logs/mysql_log

とか追加すればログが保存されるようになる。

MT4デフォルトの「検索結果」テンプレートだと、

  • 1件がマッチするキーワードでの検索: ログは122行(41クエリ)。
  • 100件がマッチするキーワードでの検索:ログは1310行!(437クエリ!)。←何ということでしょう!?

CGIの起動がネックだとか、LIKE検索せずにPerlのマッチングだけでやているから遅いとか色々と各所で指摘はされているけれども、SQLのクエリーの数だけでも相当なものだ(特にヒット数が多い場合)。

次に、「検索結果」テンプレートの「ブログ記事の概要」モジュールのところを削除して、


<p><a href="<MTEntryPermalink>"><MTEntryTitle></a></p>

のようにタイトル部分がリンクするようなシンプルな検索結果が表示されるようにする。

  • 1件がマッチするキーワードでの検索: ログは98行(33クエリ)。
  • 100件がマッチするキーワードでの検索:ログは98行(33クエリ!)。←何ということでしょう!?

これだけ差があるとCGIの起動とかPerlのマッチング云々以前に、DBが高速でない場合には明らかなレスポンスの差につながると思われる。さて、この差はなんだろう?

アクセスするテーブルが多い程クエリは増える。

犯人はコイツ↓

ブログ記事のメタデータ

MTのデータベースの構造を見てみた人なら知っていると思うけど、「コメント」や「トラックバック」、「カテゴリ」といった情報は mt_entryテーブルとは別のテーブルになっている。特に「トラックバック」や「カテゴリ」はそれぞれ mt_trackback & mt_tbping, mt_placement & mt_category というように2つのテーブルにアクセスしないといけない。あと「タグ」もそう。

よって、デフォルトの「検索結果」テンプレートにおいてマッチ数が多いときにログ(クエリ) を膨らませているのは、この「トラックバック」と「コメント」である。

もちろん、検索に限らず例えばダイナミックパブリッシングにおける一覧ページ系においてはできるだけ複数のテーブルを参照しないようなテンプレートの作り方をすれば少なくともDBへ発行するクエリの数は減る。エントリー(ウェブページ)であれば、概要欄やキーワード欄、追記欄等は同一のテーブル内。だから、記事のメタ情報について「タグ」や「カテゴリー」を利用しているけど、エントリーの概要欄やキーワード欄、追記欄を利用していない、という場合はこれらのフィールドをできるだけ活用して他のテーブルにクエリを投げる回数を減らしてやるとちょっとだけ幸せになれるかも。

もちろん、テンプレートのメンテナンス性とか管理画面のユーザビリティ的にとかそのあたりとトレードオフになる場合もあるけれど、MTのテンプレートを仕事で書く人は覚えておくべき基本の一つかもね。

「介護福祉」を学ぶ学校の取材に行ってきた。

視覚障害者を誘導? するときは、自分の右腕を左手でつかんでもらって左側一歩手前に位置して言葉をかけながら一緒に歩く。

なぜなら右手で杖を持っている人が多いので。だから利き腕が逆の人だったら反対に右側一歩手前に位置するのだ。

アイマスクをして歩いてみると、いかに「段差」が鬱陶しいか良くわかる。

話をした彼女・彼らの多くが身近な体験をきっかけにして進路を選択している。

「両親が共働きで、祖父母に可愛がってもらった」そして「祖父母が体調を崩してケアが必要になった」、とか、「過疎化で高齢者が多いところで育った(で、近所のじいちゃんばぁちゃんに可愛がってもらって、何か恩返しがしたい)」とか。皆がハキハキと、しっかりいた口調で語ってくれて少々驚いた。自分の学生時代のなんと目的意識の無くいい加減だったことよ。

皆、しっかりと挨拶するし「イマドキノワカモノ」って言葉のイメージが反転した一日だった。

1回生の夏、介護福祉の実習にはじめて行く段階で、必ず何人かは音を上げるそうだ。先生が巡回指導に行くと先生の顔を見て泣き出す人も多いらしい。ただ、2年生になると顔つきが変わってくる(取材に行ったのは短期大学)。1回生の夏をこえるのが一つのヤマなのだそうだ。何かそのあたりは話を聞いてよく理解できた。

介護福祉の仕事は人材不足。資格や就職のことを考えて進学してくる人たちが多い。地方自治体が奨学金とか色々整備しているが、むしろ必要なのはそうやって「泣ける」場なのかもしれない。学校だったら実習から戻れば仲間も先生もいる。一旦社会に出ればそういった場は殆どなくなってしまう。

介護福祉を学ぶ学校がそういう役割を果たせればといいのかな、と思った。介護福祉に限らないけど、社会に出れば辛いことやしんどいことも多いだろう。同窓会ってのは単なる思い出を肴に酒を飲む会じゃないんじゃないかな、ということを何となく考えた。

少人数であるが故、みんな仲が良くて明るい(少なくとも僕が感じた限りはそう感じたし、多くの学生たちの言葉からもそういった言葉が発せられたし)。「学校」にこそそういう役割が果たせるのではないだろうか。

「全入時代」である。大学や短大の価値ってのは、そんなところにも見いだせるんじゃないか?

転じて、自分の仕事を鑑みるならば、「ウェブアクセシビリティ」を技術的な側面で考えるだけじゃなくて、ましてや「ユーザー」のことを考えるだけにとどまらず、障碍者や高齢者を支援する人たちの目線を含めて考えることが大切なんじゃないかな。そんなことを感じた一日。

もちろん商用のCMS製品全てについて知っているわけではないのだが、Web屋の現場で感じることを少し。

「オーサー」の自由度を増すとサイトは崩れて行く

「オーサー」即ちCMSに情報を登録する「発信者」のこと。Movable Type(主にバージョン3系の話)をCMSとして使っていただくと必ずといっていいくらい「表は簡単に貼付けられないの?」とか「画像貼ったり文字に色付けたりしたい」とかいう話が出る。そして、JavaScriptベースのWYSIWYGエディタを組み込んだり、ということになって「ほらこうすると"MS Word感覚"で更新できますよ」みたいなことに落ちつく。

"WYSIWYG"は諸刃の剣

ところが、"MS Word感覚"ってのがくせ者で、実はMS Wordで(特に見栄え面で)センスの良い文章を作成できる人って少ないのです。だから、デザインの自由度をあげると殆どのケースでサイトの統一感は失われていき、せっかくCMS導入してリニューアルしたのに...ってことになりがちだ。

かといって、「WYSIWYGは使えません」だと、「自由度低すぎ」「これも出来ないの?」「あれも出来ないんだ...」という評価になるんだ。

「不自由」と「自由」の落とし所がポイント

そこで、実際は「プロの作成したできるだけ多くのパターンから選択してからページ制作を始めてもらう」「選択したパターンはあまり変えることはできない」というところにだいたい落ち着く。これまでは、MT::App:CMSのテンプレートをある程度簡単にカスタマイズしたりしていたのだが、独自のテンプレートタグを定義して(例:「CMS_Add_Field type=textarea height=200」みたいなタグを書いて)フィールドを増やしていた。

ただ、これではやはりクライアントに渡した後はお手上げになるし、覚えることばかり増えて大変だ。

Movable Type4でどこまで出来るか

MT4からは「ウェブページ」が作れるとか「アップロードしたファイルが管理できる」とか「ブログをまたがってページを出力できる」とか色々なフィーチャーがあって「CMS」狙ってるな!? って匂いはすごくするんだけど、やっぱりまだWeb屋さんの現場ではクライアントニーズにあわせたCMS自体のカスタマイズは必要だ。さもなければ不便に目をつぶって(現実路線としてお金もそんなにかけられないし) 「運用でカバー」ということになるだろう。

そこで、管理画面のGUI操作で「本当の意味で」簡単にカスタマイズが出来るものを作ろうとしていて、まだ限定的ではあるが、Movable Type4「CMS化」プロジェクトを進行中で、エントリー編集画面のカスタマイズあたりはほぼ完成した。

提供する側には「自由度が高くてオーサーのニーズに応えることが容易にできる」、一方で「オーサーは自由度は限定的だが、やりたいことは予め容易された手順で簡単にできる」ものを狙っている。

エントリー(ページ)の編集画面に一行テキスト、複数行テキストエリア、ラジオボタン、チェックボックス、セレクトメニュー、ファイル添付の各フィールドを自由に配置できる。アップロードしたファイルはエントリー(ページ)と関連づいていて、エントリー(ページ)を削除すると同時に削除される。添付したファイルはMTのassetテーブルにも格納される。

ちなみに、このサンプルのテンプレートタグの該当部分はこんな感じになっている。フィールドを増やしたり減らしたりしてもそれなりに対応できるからこんな風に自由にフィールドを増減しながらエントリー(ページ)を作ることも可能。


<MTExtFields>
    <MTIfExtFieldType type="text">
        <h2 style="font-size:120%;font-weight:bold"><$MTExtFieldText$></h2>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="textarea">
        <p><$MTExtFieldText$></p>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="file">
        <MTIfExtFieldNonEmpty>
            <MTIfExtFieldTypeImage>
                <p><img src="<$MTExtFieldFilePath$>" alt="<$MTExtFieldAlt$>" width="<$MTExtFieldImageWidth$>" height="<$MTExtFieldImageHeight$>" /></p>
            <MTElse>
                <p>Download:<a href="<$MTExtFieldFilePath$>"><$MTExtFieldAlt$></a></p>
            </MTElse>
            </MTIfExtFieldTypeImage>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="radio">
        <MTIfExtFieldNonEmpty>
            <p><$MTExtFieldText$></p>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="select">
        <MTIfExtFieldNonEmpty>
            <p><$MTExtFieldText$></p>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="checkbox">
        <MTIfExtFieldNonEmpty>
            <p>チェックボックスにチェックが入っています</p>
        <MTElse>
            <p>チェックボックスにチェックが入っていません</p>
        </MTElse>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
</MTExtFields>

とはいえ、自由過ぎると色々な問題が出てくるので...

フィールドをカスタマイズした編集画面は「エントリー(ページ)テンプレート」として保存できるので、「オーサー」は予めカスタマイズされたテンプレートを選択してページを作るだけ。現状「テンプレート」編集権限の無い人には、フィールドの増減や並び替えは出来なくしてある。

CMSが機械的に吸収出来る部分は吸収して「オーサー」に覚えてもらうことを減らすことも重要

せっかくCMSを入れても、結局「テキスト入力時には、アクセシビリティにも考慮して以下のことに気をつけましょう」なんてやってるケースが殆どかと思うけど、英数字の全角 or 半角とかそんな統一くらいはCMSでやって欲しいってのが本音な筈だよな。

以下のようなプラグインを使うことで、このあたりも入力する人にできるだけ考えさせないようにすることも重要(MT4では画像アップロード時のalt欄のところが動かないけれどテキストフィルターは正常に動作する)。

いずれにしても、現状でこのようなMT4ベースのCMSカスタマイズ案件を進めていて顧客の要望も(もちろん現場のスタッフの要望も)聞きながらつくっているので、「現場で出てくる不満」をクリアするものに仕上がってきている実感はあるけれども、まだ欲しいものが色々あるので引き続き制作を進めて行きたい。

嫌な思いをするのは結局中の人なんだよな。先に謝っておくよ。ごめんなさい(でも社内のことは社内で片付けてください)。

まずは前振り。「引用」と「肖像権」とについて。

色々なサイトのスクリーンショットを 自分のサイトで使用すると法的に問題があるのでしょうか? 私個人としては常識の範囲内なら良いとは思うのですが。 良いと思う、悪い.. - 人力検索はてな

他人のサイトの画像をそのサイトの紹介や批評にする際に自分のページに掲示することは、引用といって法的に認められた権利です。

ふむふむ。ってかそれは知っている。

確実にアウトとなるのはそのHPにタレントの写真が用いられていた場合です。その場合は肖像権の侵害となり、訴えられることになるでしょう。

「確実にアウトになるんだ?」まぁその辺りは当事者が考えなよ。ってか、確実にアウトだったらmalaが可哀想だろ。誰か全力で反論してやれよ。

*俺自身は「確実にアウト」になると考えるわけではなくて、それは「権利」を持っている側が訴えることが前提となるわけだから、今回はおそらくそうはならないだろう(火種が大きくならない限りは...てかそれほどの影響もあるまい)。いずれにしてもかなりグレーだと考えるわけだよ。憲法読めとか引用知らんのかとかありがとうございます(大きなお世話だけどさ)。

たださぁ、「だからスクリーンショットも張った。」って本人も言ってるじゃん。覚悟の上で言ってるんだろ? 周りが察してやれよ。

ここから本題。NOWAの利用規約を見てみような。 (利用規約は飾りじゃないだろう?)。(強調は俺ね)

第6条 (責任及び注意義務について)

利用者は、自己の責任に基づき本サービスを利用するものとし、利用者が公開するブログについて、全ての責任を負うものとします。また、利用者は弊社に対し、他人の著作物を使用したことなどが原因で紛争、損害賠償の請求などが起こった場合の損害、責任について一切を免責するものとします。(後略)

第7条 (禁止行為)

利用者の本サービスの利用にあたって弊社は以下の行為を禁止します。利用者がこれらの禁止行為を行った場合、弊社は当該利用者のブログを削除し、以後の利用を禁止する場合があり、それによって利用者が何らかの損害等を被ったとしても、一切の責任を追わないものとします。

・本規約に反する行為
・法律・規則・条令等の制定法に反する行為
(中略)
・利用者以外の自然人・法人・団体・組織等の第三者の名誉や社会的信用を毀損したり、不快感や精神的な損害を与える行為
(中略)
・利用者以外の自然人・法人・団体・組織等の第三者の所有する知的所有権を侵害する行為や、著作権の侵害を誘発する行為
・その他弊社が不適切であると判断する行為

サービス提供側が責任を負わないと書くのはもちろんよく分かる。会社が云々とか書いてすいませんでした。

なので、法律云々は置いておいて (最終的には裁判でもしてみなければ結論は出ないかもしれないが、タレント事務所とサービス提供者がどんな契約をしているかが重要だろうし、それを知る術がないので置いておく、という意味)、「これは完全にエンジニアが無知で無能でクズ。アホでバカ。低脳でワーキングプア。」ってのが 「利用者以外の自然人・法人・団体・組織等の第三者の名誉や社会的信用を毀損したり、不快感や精神的な損害を与える行為」にあたるかどうかってのと「第三者の所有する知的所有権を侵害する行為や、著作権の侵害を誘発する行為」の2点についてどう考えるべきかについてサービス提供者の見解が聞いてみたい。って言うだけ無駄だろうがね。

規約が飾りだったら規約なんか書かなくていいんじゃね? そんなWebサービスだったら辞めちゃえば?

*もちろん、エントリーを書いた時点でこのあたりを熟読して論理的に考察していたわけでないことは認めるよ。それが気に触ったのならごめんなさいね。

ついでだからアメブロの利用規約も見てみよう。

第11条(知的財産権等)
本サービスを構成する文章、画像、プログラムその他のデータ等についての一切の権利(所有権、知的財産権、肖像権、パブリシティー権等)は、会員自身が作成したものを除き、弊社又は当該権利を有する第三者に帰属しています。
会員は、会員自身が作成した著作物を本サービスを通じて掲載した場合、弊社が宣伝告知等に利用することを許諾するものとします。また、かかる使用に際して、当該会員は著作者人格権を行使しないものとします。

なるほど、著作者人格権は行使できない、と。但しこの利用規約をベースにタレント事務所と契約していないだろうし、タレント事務所等とは別の何らかの契約を交わしているだろうよ。アメブロの「タレントブログ」にどの程度の縛りがあるかは知らないが、メディアにタレント使う時には制限事項や契約期間とかの縛りとか細かに書いた契約書交わすのが普通だよね。

第12条(禁止事項)
全利用者は、本サービスの利用に当たって、以下各号の行為又はそのおそれがある行為を行ってはならないものとします。
(1)弊社又は第三者の所有権、著作権を含む一切の知的財産権、肖像権、パブリシティー権等の正当な権利を侵害する行為
(中略)
(3)公序良俗に反する行為
(4)法律、法令等に違反する行為
(中略)
(7)サービスの信用を失墜、毀損させる行為
(後略)

「全利用者」の定義としては

「全利用者」---弊社が情報提供するサービスを利用する全ての者

とあるので、アメブロのサービスを利用してブログを書く者に加えて、閲覧する者、引用する者、又二次的に情報を加工若しくは利用する者(WebサービスとしてのRSSリーダーとか) 等が含まれると考えるべきなのだろう。

考えておくべき内容としては「サービスの信用を失墜、毀損させる行為」というあたりだろうよ。CAは黙ってんの? 大人だねぇ。CAが大人で良かったよな。

最後に、これもまたついでに (これがまぁ一番どうでもいい話題だけどね) はてなの利用規約。

第6条(禁止事項)
2.ユーザーは、本サービスを利用するに際し、以下のような社会的に不適切な行為を行ってはなりません。
(中略)
4.迷惑行為、嫌がらせ行為、誹謗中傷行為、正当な権利なく他者に精神的被害・経済的被害を与える行為

NOWAやアメブロは分かりやすかったが...(守られてるかどうかは全く別だが)「正当な権利」の定義が知りたいと思うが「正当な権利があれば他者に精神的被害・経済的被害を与える行為は可」と読めたりしてこのあたりは現状を踏まえて敢えてこうしているのだろうか? だったらこれ書いた人に拍手。いや、良い意味で(「はてな」ってそのあたり考えるとすげぇ会社だよ、いやマジで)。

まぁ、あんたがたの会社にはこういった規約を真面目に考えて作ってる人がいるわけだ(虚しい仕事だろうがね)。

もう一度言おう。意味が無いなら消しちゃえば?

ハッカー格好いいから、スーツの意見なんか無視しちゃえばいいし、エンジニアに恥をかかせる会社もこき下ろせばいいってか? まぁ好きなようにやればいいじゃん。良い意味で。

最後にさぁ、こんなの作ってらっしゃるようですがねここの利用規約も読んでみようよ。

他の利用者又は第三者、若しくはライブドアを差別若しくは誹謗中傷し、又は名誉若しくは信用を傷つける行為

他の利用者又は第三者、若しくはライブドアの財産、プライバシー、肖像権若しくはパブリシティ権を侵害する行為、又は侵害するおそれのある行為

ライブドアは社員が自社サービスの利用規約を守れなくても放置する会社ですか?

制作途中のものをこうやってアップして晒すってのはどうなのよって気もしないでもないけど、これもまぁマーケティングの一つの方法だよな。あと、何作ってるよ、いつくらいにリリースできそうだよってのを共有すると別の人が同じもの作らなくて良くなるからユーザーコミュニティにとっても良いことだろうしね。

ExtFieldsの画像添付

例のごとくQuickTimeムービーにしてみた。

ブログ(Movable Type) の投稿インターフェイスの中で、ファイルのアップロードがやっぱり面倒だという声が(主に社内で)出ていたので、汎用的に実装できるように制作中のExtFieldsプラグインに「input type=file」のフィールドも自由に追加できるようにしてみた。

同名ファイルが存在していた時の上書き確認とか同時にAssetテーブルにデータを保存するとか upload_file コールバックをちゃんと呼び出すとか削除はどうすんの、とかこいつはちょっとホネのある作業になりそうな気配だけど何とか今月中には完成させたい。

あと、「フィールドの並べ替えができると便利ですかねぇ」という声もあったので実装してみたよ。エントリー投稿画面をクライアントニーズにあわせて簡単に変更できるから、CMSのカスタマイズがめっちゃ簡単になる(予定!)。

でもって、こっちが並び替えのムービー。

プレビュー画面に追加されたボタン

プラグインの設定

pluginsフォルダにフォルダごとアップロードするだけで特に設定は必要ありません。Another HTML Lint のcgiのURLを変更する場合のみプラグイン設定画面からアドレスを登録してください (初期設定ではプライマリサイトのゲートウェイのアドレスに設定されています) 。

プラグイン設定画面

尚、Another HTML Lint はチェック項目について細かな設定ができるようになっていますが、このプラグインでは[Lite]バージョンのフォームのデフォルト設定と同じになっています。変更する場合はプラグインのソースを修正してください。

ご利用について

パブリックドメイン。利用に制限は設けません。

ちなみにAnother HTML Lintは非営利目的の利用に限りフリーです。うちの会社では『「Web屋さん」の利用』にあたるので利用料を払って使用しています。

ダウンロード

設置方法

前回のエントリーを参考にしてください。

  • htaccess又はhttpd.confでmod_alias又はエラードキュメントを設定する(ここは自動化されていません)
  • mt-confg.cgiに「CookiePath /」を追加(テストのためには一度ブラウザのクッキーを削除する必要あり)
  • プラグインの設置/設定→保存(設定項目は以下の通り)

SimpleAuth設定画面

プラグインの設定

  • ドキュメントルートのパス
  • Apacheでアクセスを制限する拡張子
  • 認証付きページにしたいディレクトリ(改行区切り)
  • Directoryへのアクセスの際に返すファイル(カンマ区切り)
  • 404エラーの時に表示させるファイルのパス

パスはいずれもフルパスで記述します。


制限事項/いけてないところ

すごく簡易的なものです。ムービーの通り画像等のアップロードしたファイルにも対応しています。但し、対応しているのはGIF/PNG/JPEGのみで、その他のフォーマットのファイルではContents-Typeヘッダが正しくセットされません。

また、MTのBootstrap.pm を利用したアプリではpragma no-cacheヘッダが付加されるのでクライアントキャッシュがうまくつかえませんし、大きなファイルを扱うことも考慮していません(Perlスクリプトを経由してファイルのデータが処理されるため、アクセスの多いページには不向きです)。あと、設定がちょっと面倒なところでしょうか。

場合によっては潔くダイナミックパブリッシングにしてそのプログラムの中での対応を考えた方が良いかもしれません。ただ「手っ取りばやく、画像等にもアクセス制限をかけたい」場合には使えると思います。

ご利用について

パブリックドメインとします。完全に無保証ですが利用に制限は設けません。

ダウンロード

ログインユーザーだけがページを見られるようにしたいってニーズは結構あるようなので。一例を紹介してみる。

追記 : プラグインにしてみた。

考え方

ダイナミック・パブリッシングであればページを生成してリプライするプログラムの中でログインの有無を設定してやれば良い。静的生成の場合はどうするか?

  • MTのクッキーの有効範囲をサイト全体にする
  • 生成されるファイルの名前の後ろに(例えば) .deny を付けるようにする (アーカイブ・マッピングの設定でも良いし、build_file コールバックに対応したプラグインを書いても良い
  • ユーザー限定ページのディレクトリに対するApacheの設定で.denyへのアクセスを拒否する
  • ユーザー限定ページのディレクトリに対するApacheの設定でmod_rewrite又はNotFoundの設定によってリクエストがプログラムに渡るようにしておく
  • プログラムの中でログインの有無をチェックするようにする
  • 例えば example.html ページが存在しない場合、ログインユーザで且つ example.html.deny が存在すれば example.html.deny の中身を返す

以下、MTが /mt以下に、/authディレクトリ以下をログインユーザー限定ページにしたい場合(ファイルのリネームのところは省略します。build_fileコールバックが呼ばれた時に /authディレクトリ以下だったら.denyを付けてリネームするプラグインを書けば良い)。

/mt/mt-config.cgi


CookiePath /

/auth/.htaccess


<Files ~ "¥.(deny)$">
    Order allow,deny
    Deny from all
</Files>
Options -Indexes +SymLinksIfOwnerMatch
  <IfModule mod_rewrite.c>
  <IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.htm default.htm default.html default.asp
  </IfModule>
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ /mt/plugins/SimpleAuth/SimpleAuth.cgi [L,QSA]
</IfModule>

<IfModule !mod_rewrite.c>
  ErrorDocument 404 /mt/plugins/SimpleAuth/SimpleAuth.cgi
  ErrorDocument 403 /mt/plugins/SimpleAuth/SimpleAuth.cgi
</IfModule>

/mt/plugins/SimpleAuth/SimpleAuth.cgi



#!/usr/bin/perl -w

use strict;
use lib 'lib';
use lib '../../lib';
use lib '../../extlib';
use MT::Bootstrap App => 'SimpleAuth';

/mt/plugins/SimpleAuth/lib/SimpleAuth.pm


package SimpleAuth;

use strict;
use MT::App;

@SimpleAuth::ISA = qw(MT::App);

sub init_request {
	my $app = shift;
	$app->SUPER::init_request(@_);
	$app->add_methods( auth => ¥&_auth );
	$app->{default_mode} = 'unprotected';
	$app->{requires_login} = 1 unless $app->mode eq 'unprotected';
	$app->add_methods( unprotected => ¥&_unprotected );
	$app;
}

############################################################################## 

#Setting

my $base = '/Applications/MAMP/mt4local2';
my $suffix = '.deny';

##############################################################################

sub _unprotected {
	my $app = shift;
	my $login = $app->login;
	if (defined $login) {
	    return &_auth($app);
	} else {
	    $app->set_header('Status','401 Unauthorized');
	    return 'Requires Login.';
	}
}

sub _auth {
    my $app = shift;
    my $path = $app->param('path') || $ENV{"REDIRECT_URL"};
    $path =~ s/¥.¥.//g;
    my $file = $base.$path.$suffix;
    if (-f $file) {
        open(FH, $file) or die;
        my @data = <FH>;
        #$app->set_header('status', 200);
        $app->send_http_header();
        $app->print(@data);
    } else {
        $app->set_header('Status','404 File Not Found');
        return 'File Not Found.';
    }
}

1;

html以外のファイルを処理する場合は拡張子からContent-Typeを識別して付与してやるとか、ディレクトリへのアクセスだったら /index.html を探すようにするとか、そのあたりの処理は必要ですが、基本的にはこんな感じ。

前回1行テキストとテキストエリアの追加のデモを載せてみたのですが、ラジオボタン,セレクトメニュー,チェックボックスにも対応させてみました。CustomFieldsとかRightFieldsとかもそろそろリリースなのかな? ちなみにプロジェクト名称は「LeftFields」!

ExtFieldsによってカスタマイズされたエントリー編集画面

あと、TemplateSelectorとDuplicateプラグインと組み合わせて「エントリーのテンプレート」を複数登録しておいて、そいつをサムネイル画像を見て選択できると便利かな、と思ってやってみた。

あとは...type="file" に対応させるかどうか迷っている。「プレビュー」の時に一時保存させるとか、プレビュー後のreeditの時に値(ファイルの選択状態)を引き継げないので...Flexだったらできるんだろうか...

「エントリーテンプレート」を「変更できる/出来ない」の権限部分(テンプレート編集権限に対応させる予定)、ExtFieldを「扱える/扱えない」の権限部分(エントリーの編集権限に対応させる予定)をやる予定。

カスタムメニューとカスタムダイアログを登録してみた。Dialogのところでargsが設定できないっぽいのはちょっと...だけど、別のモードを作ってパラメタ設定してから $appと一緒に別の関数に渡してやればいいのであまり気にしていない (でもダイアログでも args設定できて欲しいと思った)。

というか、以下のページに載っていたそのまんまやってみただけだけど、SNAPZ Pro Xが楽しいので何となくのっけてみてます。

こういった標準的に用意されている拡張方法に沿って開発すると一貫したUIっちゅうもんが保てるのだね。

ちなみにメニューは左からcreate(新規作成), manage(一覧), design(デザイン), prefs(設定/ブログ), tools(ツール/システム)という名前になっている。orderのところでどんな数字を指定するかで表示順を設定できるのだが、このあたりは /Lib/MT/App/CMS.pm を見てください、ということで。


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                menus => {
                    'create:example_dialog' => {
                        label => 'Dialog Sample',
                        dialog => 'select_dialog',
                        order => 99,
                        permission => 'publish_post',
                        view   => "blog",
                    },
                    'manage:example_menu' => {
                        label => 'Menu Sample',
                        mode => 'select_menu',
                        order => 999,
                        args => { foo => 'bar',
                                  bar => 'buzz' },
                        permission => 'publish_post',
                    },
                },
                methods => {
                    select_dialog =>
                        'MT::Plugin::Menu::select_dialog',
                    select_menu =>
                        'MT::Plugin::Menu::select_menu',
                },
            },
        },
    });
}

一応サンプルもあげておきますね。

SNAPZProX2.1.1面白い!

Snapz Pro X

何か久しぶりにデスクトップアプリを買った。衝動買い。デスクトップ画面をムービーとしてキャプチャすることができるMacOS X用の高機能キャプチャソフト。ダウンロード販売で税込み8,820円。

オンラインマニュアル作成なんかに良いと思うのだけど、例えばウェブアプリ開発の時のテストとか進捗報告なんかに使えるんじゃないか? っていうか、ブログに掲載するのにキャプチャ貼付けて解説文章打ち込んでって面倒じゃない。

ということでまだ作成中なんだけど、何か面白い感じのものが出来た! とか、あぁやっとここまで出来た、っていう途中段階のものを晒してみるのも面白いんじゃないかと。飽きるまでしばらくこんな感じでのせるかもしれない。

今日のは、この↓プラグインをちょっと根本的に書き換えようと思っていて、インターフェイスとか機能とかをちょこちょこと追加した様子のご紹介。

管理画面でテンプレートのバリエーションを作ってエントリー編集画面で別のテンプレートを選択できるんだけど、テンプレートの名前だけじゃなくてテンプレートのサムネイルを登録できるようにしたら面白いというか使いやすいのではないかと。で、どうせならMT4の「カスタムダイアログ」を使ってみようということで、このあたり(How to Create a Modal Dialog) を参考にしながら実装。

ちょっと重たいです(20MB程あります)

まだ作成中だけど出来ているところまでのデモムービーをアップしたよ!

ExtFieldsで拡張したエントリーの編集画面

これもまた作成中のものだけど、以下のプラグインあたりと組み合わせて使うことでクライアントの要件に沿ったCMSを簡単に構築できる(ものになる筈)。

カスタマイズした編集画面を「ひな形」的に保存・登録できるから、複数のパターンから好きなものを選んで投稿できるし、各パターン毎に出力するテンプレートを切り替えることもできる。

条件タグなんかで出力条件をカスタマイズすることもできるし、このムービーの例では、textだったらdt、textareaだったらdd にしてループさせるようにテンプレートタグを定義している(だから、その場でフィールドはどんどん増やしていける)。

こんな感じね。


<MTIfExtField>
 <dl>
  <MTExtFields>
  <MTIfExtFieldType type="text">
   <dt style="font-size:120%;font-weight:bold"><p>
  <MTElse>
   <dd style="margin-left:20px"><p>
  </MTElse>
  </MTIfExtFieldType>
   <$MTExtFieldText$>
  <MTIfExtFieldType type="text">
   </p></dt>
  <MTElse>
   </p></dd>
  </MTElse>
  </MTIfExtFieldType>
  </MTExtFields>
 </dl>
</MTIfExtField>

もちろん決め打ち? もできる。


<$MTExtFieldText label="label1"$>

リリースの時期とライセンスは未定だけど、最終的にはMTOS用とMT用のデュアルライセンスとか考えてます。

* いや、MT4、いじりがいがありますよ!


追記:

こんな感じにすると、「名前」で指定したタグで囲まれることになる。例えば「名前」を「h1」とか「blockquote」とかするとそのダグで囲まれるわけだ。


<MTExtFields>
 <<$MTExtFieldlabel$>>
  <$MTExtFieldText$>
 </<$MTExtFieldlabel$>>
</MTExtFields>

ついカッとなってエントリーを投稿するとろくなことにならないってのは、まぁみんな共通の問題として考えればいいんじゃないかな。

ブクマコメントのひとつひとつにマジレスはしないけど、考えるべきは「会社」というものの中で (プライベートではあるものの所属が明らかな場合の)「ブログ」で「どこまでが良くてどこまでが良くないか」ということじゃないのか。だから僕が本人に直接っていうのはちょっと意味が違ってて、それぞれの会社で考えれば良いのだ。

# もちろん「あり」というのならそれはそれで良いと思う(いやマジで)。

さて...

ここからが本題。というか既に駄文でネタで釣りだけど。結局、大切なのは「公開」する前にひと呼吸置くということだな...

インストール後のエントリー「保存」ボタン

エントリーの投稿画面での「保存」ボタンを変えてみた。せっかくなので晒しておく。MT4専用。

あ、一応これはシリーズもの? で名前は「Mo[e]vableType」と言う。

画像は再構築バージョンのものをそのまま使ったので必然的に「クリエイティブ・コモンズ 表示-継承 2.1」ということになる(営利目的の利用もOK)、だからlivedoor ブログに採用していただこうが nowaに採用していただこうが僕は全然構わない :-p

# またカッとなってやってしまった...

ここ1〜2週間程、怒濤のMTプラグインリリースラッシュ? なわけですが、MTを拡張したりMTベースでウェブアプリケーションを開発するにあたっては、データベースを拡張したいケースが当然出てきます。DBの拡張方法は以下のエントリーでもご紹介していますが、簡単に作れたらいいな、ということでMTObjectBuilderというものを作ってみました。

関連するエントリー

MTObjectBuilder

フォームへ必要事項の入力

MT::Objectのサブクラス作成画面

  • プラグイン名を入力
  • 拡張クラス名を入力
  • add clumn をクリックしてカラムを追加
  • カラム名を入力, Typeを選択, 必要であればIndexにチェック
  • 親クラス(指定があれば)を入力(例: Child of MT::Entry)
  • Createをクリック

モジュールとプラグインのソースが生成される

生成結果

ファイル(2つ)を作成して保存

  • 生成されたソースをエディタにペーストしてそれぞれをファイルとして保存

ファイルとして保存

MTへアクセスしてデータベースをアップグレード

  • MTにアクセスするとUpgraderが起動する

アップグレード画面

アップグレード完了

正しく生成されていることを確認

PHPMyAdminで確認

台風から逃げる。

| コメント(0) | トラックバック(0)

新700系

喫煙室

連結器?

台風やりすごしてから帰るか迷ったのだが、何だかきっかけがあったので今から大阪へ帰るとする。

二度目なので嬉しがって車内で写真とりまくったりしない(してるやん)。

プラグインについて

未だに「エントリー」と言った方が通りが良いと思いますが「ブログ記事」「ウェブページ」を複製できるようにするプラグインです。

CMSの設計と運用方針次第ですが、このプラグインが本領を発揮するのはカスタムフィールド等を使って投稿画面をカスタマイズしたり、拙作の「TemplateSelector 」のようなテンプレートを切り替えたりするカスタマイズを施している時かと思います。

このブログでも再三取り上げた通り、MT4をCMSとして拡張するためのプロジェクトを現在進行中で、そのプロセスで作成した一つのプラグインです。

関連エントリー

ライセンス

クリエイティブ・コモンズ・ライセンス (表示-非営利-継承 2.5)

※業務でのご利用はご相談ください。公開しているすべてのプラグインのライセンスについてはMTOSが正式リリースされた折には見直したいと思います。

利用方法

プラグインを利用するだけで特に意識することなく直感的に利用できると思います。

プラグインをインストールすると、下記のように「ブログ記事」「ウェブページ」の一覧に「複製」ボタンが表示されます。

ブログ記事の一覧に追加されたボタン

また、各エントリー(「ブログ記事」「ウェブページ」)の編集画面の下部のボタンにも「複製」ボタンが追加されます。

エントリー編集画面に追加されたボタン

「複製」ボタンをクリックして編集画面に移動された段階で、各フィールドには複製元のエントリーの各値が入っています(但し、タイトル部分を見ていただければ分かる通り、この段階では「ブログ記事(または「ウェブページ」)の作成」扱いとなっています(この段階ではまだエントリーは保存されていません)。

エントリー編集画面のタイトル部分

ダウンロード

ならなくて済むのならね。っていうか、あなたが制作者ならば評論家になんてなるんじゃねぇぞ。批評は評論家に任せておけ。

*某SNSへのリンクでごめんなさい( あと、この調査に対する批判のつもりではない。以前から行われているこの調査のことは知っていたし、すごく参考にさせていただいていることは事実) 。

何が言いたいかというと、某SNSにはニュースを元に日記が書けるようになっていて、まぁみんな色々書いてるけどその日記を書いているSNSの入会に携帯アドレスが必要ということが視覚に障害のある多くの方に対して参加障壁になっていることとか、そのあたりも考えておけよなってこととか。

あとね、水○庁のサイトがどうとか、イケてないからデザインしちゃえ! とかIA的に考えると...とか考えて実際に企画しちゃう感覚ね。

別に僕が国の関係の仕事もやっているから言うんじゃないけどね、イケテないと思えば提案持っていけばいいじゃない。そしてその制約(予算とか契約とか)の中でちゃんと結果を出せるなら堂々と営業して企画競争でも入札でも参加すればいい。

もちろん、I区の担当者もS庁の担当者も限られた条件の中でそのサイトを作ったわけだ。もちろんそれは仕事だから「使いにくい」って言われたらそれは何とかしないといけない。でもそれは「利用者」でも「カイゼン案を提案してきた営業の兄ちゃん」でもない「誰か」に言われる内容でもなかろう。問題提起することを否定はしないし調査結果を公表することを否定はしない。ただ、公表するよりも提案することの方が僕たち(制作者)には大切だ。これは立ち位置の違いに起因することかもしれないが。

他にも色々あるよね。「これこれの業種のサイトの使いやすさランキングの上位はここ」などとニュースリリースするコンサル屋さんとか(ランキングして何が楽しいんだよ! 暗いなぁ)、ウェブ屋の作るサイトには100%脆弱性がありますとかのたまう某業界の人とかね。

プロ野球の監督の采配に対してだって批判は簡単(もちろんオシムにだって批判はできるぜ)。大切なのは「評論」ではなく、「カイゼン」だよ。だから、批評は評論家に任せておけ。少なくとも「制作者」はプライドを持って、「評論家になんてなるんじゃねぇぞ」。

メモ。

MTの「コア」のテーブルにカラムを追加するのってどうなのよ! バージョンアップの際にも困るんでないの? ってかプラグインみたいな気軽に付けたり外したりするものでカラムを追加するのってさぁ...というお話があがっているので素直にMT4でMT::Objectを継承したサブクラスを作ってDBのテーブルを拡張する方法でやってみようかと。

モデルは数日前に作った「TemplateSelector」プラグイン。

# 何とか出来たっぽいけど効率が良いとは言えないなぁ...ということでテストも不十分だしまだ公開はしない。あくまでも備忘録です。

TemplateSelector(改)プラグインの構成

Selector.pm をプラグインフォルダの lib/TemplateSelector 以下に設置


plugins/TemplateSelector/lib/TemplateSelector/Selector.pm

Selector.pm


package TemplateSelector::Selector;
use strict;

@TemplateSelector::Selector::ISA = qw( MT::Object );
__PACKAGE__->install_properties({
	column_defs => {
		'id' => 'integer not null auto_increment',
		'blog_id' => 'integer not null',
		'entry_id' => 'integer not null',
		'template_name' => 'string(255)',
	},
	indexes => {
		blog_id => 1,
		entry_id => 1,
		template_name => 1,
	},
	child_of => 'MT::Entry',
	datasource => 'selector',
	primary_key => 'id',
});

1;

TemplateSelector.pl


use TemplateSelector::Selector;


中略

sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        object_types => {
            'selector' =>  'TemplateSelector::Selector',
        },

以下略

これで、プラグインを「new」する時に schema_version を指定してやればUpgraderが起動してデータベースにテーブルを追加してくれる。

Selector.pmで「child_of => 'MT::Entry',」とすることで、該当のエントリーが削除されたらSelectorの該当するフィールドを削除してくれる。このあたりはさすが!

entry_idで紐付をして、エントリーがどのテンプレートを選択しているかを template_name に突っ込みたいが、これはさすがに自前でコードを書く必要がある。カラムの拡張ならフォームのname属性をtemplate_nameにしたセレクトメニューとかチェックボックスを用意すれば保存時に勝手に保存してくれる。これが便利すぎて嫌になる(カラムを拡張する誘惑に負けそうになる)。

気を取り直して、コード部分。

init_registryにコールバックを登録する。

  • 'MT::App::CMS::template_source.edit_entry' → セレクトメニューを登録するTransformer
  • 'cms_post_save.entry'→エントリーが保存された後処理(このタイミングで処理する)

TemplateSelector.pl (続き)


        callbacks => {
            'MT::App::CMS::template_source.edit_entry'
                => ¥&_add_template_selector,
            'cms_post_save.entry'
                => ¥&_entry_selector,


中略

sub _entry_selector {
    my ($eh, $app, $obj, $original) = @_;
    my $q = $app->param;
    my $template_name = $q->param('template_name');
    my $id = $obj->id;
    my $sel = TemplateSelector::Selector->load({ entry_id => $id });
    if ($template_name) {
        unless (defined $sel) {
            $sel = TemplateSelector::Selector->new;
            $sel->entry_id($id);
        }
        $sel->template_name($template_name);
        $sel->blog_id($app->blog->id);
        $sel->save or die $sel->errstr;
    } else {
        if (defined $sel) {
            $sel->remove or die $sel->errstr;
        }
    }
}

これで、エントリーが保存されるのと同時に selector_template_name が保存されるようになった。

これで「出来た!」という程世の中甘くなかったよ。問題はテンプレートを選択した時のプレビュー(「確認」ボタンクリックした時の画面)。プレビューではテンプレートが選択されたテンプレートになってくれない。一旦エントリーを保存すれば良いわけだけど、これは多分「あり得ない」仕様だろうなぁ。テンプレートを切り替えてもエントリー公開するまでデザインが確認できないなんて!

ということで、プレビューも自前で実装(何とかならんものか)。でもこれやっとかないと「フィールド拡張」も出来ないし。

コールバックに以下を追加。

TemplateSelector.pl (さらに続き)


            'MT::App::CMS::template_output.preview_strip'
                => ¥&_style_preview,

CMS.pmのコードを読むと、未保存のエントリーのプレビュー時には entry_id(-1) としてるようなので、一時的に TemplateSelector::Selector->new;して entry_id(-1) として selector_template_name にテンプレート名をセットして保存、プレビュー用のHTMLをbuildしたらそのレコードは削除することにした。


sub _style_preview {
    my ($eh, $app, $tmpl) = @_;
    my $q = $app->param;
    my $id = $q->param('id');
    my $template_name = $q->param('template_name');
    my $sel; my $org_templ_name; my $tmp_sel;
    unless ($id) {
        $sel = TemplateSelector::Selector->new;
        $sel->id(-1);
        $sel->entry_id(-1);
        $sel->template_name($template_name);
        $sel->blog_id($app->blog->id);       
        $sel->save or die $sel->errstr;
    } else {
        $tmp_sel = TemplateSelector::Selector->load( { entry_id => $id } );
        if (defined $tmp_sel) {
            $tmp_sel->template_name($template_name);
        }
    }
    my $blog = $app->blog;
    my $blog_id = $blog->id;
    my $tmap = MT::TemplateMap->load(
                            {    blog_id => $blog_id,
                                 archive_type => 'Individual',
                                 is_preferred => 1
                            },);
    my $template = MT::Template->load({id => $tmap->template_id});
    my $preview_tmpl = $app->translate_templatized($template->output);
    $$tmpl = $preview_tmpl;
    unless ($id) {
        $sel->remove or die $sel->errstr;
    }
}

とりあえず「保存」ボタンとか「エントリー編集画面に戻る」ボタンが無いので「ブラウザのバックボタン」で戻ってね状態だけどプレビューにテンプレートの変更が反映されるようになった。フーーーッ! 結構面倒だなぁ、というのが正直な感想。

MT3.xでも有効な例はこちらに↓。

こういう反応は単純に嬉しいわけだけど(ちゃんとわかってるじゃない! という面で)、僕自身も仕事について考えてみる(というか考えていることを書こう)。

対象は「WEB制作者」。「Web屋」とか、職種の括りで言えば「Webプロデューサー」とか「Webディレクター」とか「Webデザイナ」とか「マークアップエンジニア」とか、まぁどうでも良い。

「ユーザー」の定義が変わったらやることも変わるのは至極当然

ここ数年で一番変わったのは「ユーザー」の定義かと思う。

「ユーザー」とは「Webサイトを利用する人」。

ってのがこれまでの定義。だからこれまでの制作者に求められたのは「利用者」に対するデザイン。 今は...

「ユーザー」とは「Webサイトを利用する人」に加えて「Webサイトを運営する人」。

CMSへのニーズの高まりもそうだし、だからこそ「再構築うぜぇからMTじゃなくてWPだよ」みたいな話が出る。つまり、「利用者=利用者+運営者」の構図。

この時制作者に求められるのは何か? やはり「利用者」に対するデザイン。但し、「利用者」の定義が変わっているから、アウトプットのデザインだけじゃ駄目だ。つまり、制作者には『「運営プロセス」のデザイン』が求められているわけだね。

どんなCMSを提供するか、っていうのは『どんな「コンテンツ・マネジメント」のしくみをデザインするか』ということなのだ。

少し古いエントリーになるが、このあたりに書いたことにもつながるかもしれない。

CMS選択の鍵は「プロセスのデザインしやすさ」

だから、『既存のCMSアプリケーションパッケージを選択して導入設定して提供するだけ』というやりかたは『企業サイト向けの既存テンプレートを購入してロゴ差し替えて納品する』ってのとあんまり変わりがないのだね。

つまり、「使う人」の定義が変わったら、「制作者」も発想を変えないといけない。だからCMSは「プロセスをデザインしやすいもの」であるべきなのだ。そういう点でWeb制作者はサイト運営のためのしくみ(プロセス)もデザインできないといけなくなっていると言える。

だから僕はWPではなくMTを使う。このあたり↓で書いていることもそれにつながっているのだと思う。

ちょっと話題からずれるけどMTのDBの拡張について

実際にこのプラグインは1時間程度で作成したものである(1時間かかってないかも...)。mtos-ja のメーリングリストとかでDB拡張に関する話題が出たのだけれど、やっぱりテーブルを拡張すると保存や読み出しのためのコードを自前で書かなくてはならなくなるし、既存テーブルへのカラムの追加ならMTが色んなものを吸収してくれるからすごく楽だ。テーブルを追加するとコードは2倍くらいに増えて工数も2倍に増える。とはいえ2時間なんだけどね。

だから、カラムの追加がスマートじゃないのはわかる。テーブル追加して、同じくらいのコストで拡張できるようにしてくれれば (あるいはドキュメントを充実してくれるだけでも良い) 素直にそうするかもしれない。

僕では集客できないですよ! と以前もモデレーターの方には伝えたのですが...お呼びいただいたので性懲りも無く人前に出るとする。

9月29日(土)です。告知しておきます。

せっかくなので、何を話すか書いてみる。

今回は、より具体的な話をしたいと思う。「MTの人(?)」であると同時に「マークアップエンジニア」ネタに絡むオッさんってのが僕のポジショニングだから。つまり、今回は「CSSer ステップアップカンファレンス」でもある、という話をしたいと思う。

何で僕がこの手のネタに過剰に反応するかというと、実はこのエントリー(マークアップエンジニアが次に取り組むべき5つのテーマ。)は僕が辿ってきた道を書いたに過ぎないからだ。つまり、(X)HTMLとCSSばかり書いていた時期が僕にはあるのだ。

そのベースにあったのは「ウェブアクセシビリティ」だったりするのだけど、とにかく『「Table」をレイアウトに使う』ってその発想はなかったわ! な時代からHTMLを書いていた人間にとってCSSによるレイアウトは敷居が高かった。

僕が他の人と唯一違ったところは、「良いマークアップ」をするためにプログラミングを覚えたところでしょうか? マークアップのためにエディタ作ったり。

こんなものを作ったりしていた(Made by REALbasic)。

* で、これはこれで今も結構使えるかも! ということについては今度書く。

そして、サーバーサイドのプログラミングを覚えたのはWSM、AppleScriptとかでCGI動かしてたわけです。

JavaScriptも好きだし、JavaScriptネタを入れてもいいけど、話がぶれるので今度はMTネタに終止するようにする。MT楽しいよ。MT4!

本題に戻って、今度のイベントで何を話すか。蒲生さんからは秋葉と同じネタでいいよ! って言われてたけど僕がそれじゃ納得いかない。だからご意見いただいたようにより「実践」ネタを話す。例えばこれとか。

他にもネタは色々あるから今後もブログにアップしますよ。あとね、真面目に募集中なのと、まぁ何だかわからないけどこんな僕と一緒に飲みたいという人は是非。

↓募集の件はこのあたりを参照くださいませ。

皆さんにお会いできるのを楽しみにしてます。

ちなみに、前回(秋葉原)のスライドはこちら。

Facebook

Twitter

このアーカイブについて

このページには、2007年9月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2007年8月です。

次のアーカイブは2007年10月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.2.6