Joomla! の携帯対応を考える

※この話題はJoomla! 1.0.x に特化しています。

 Joomla! は優れたCMS だが、日本向けWeb サイトを構築するにあたって、致命的な欠陥を抱えている。

 というのも、com_content コンポーネントが標準で出力するHTML が携帯向けではないのだ。

 XHTMLCSS が使える3G 携帯が増えてきているとはいえ、未だに多くのWeb サイトで古い携帯端末への対応を余儀なくされている現状を考えると、「Joomla! は使えない」という判断がなされても仕方が無い。

 以前「金魚屋開発支援シリーズ」で発表した「コンテンツVIEW コンポーネント」のような専用のコンポーネントを使う、という手もあるが、これはコストがかかりすぎるし、ブログカテゴリやセクションリストのようなJoomla! の便利な機能を使えないのは痛い。

 そこで、出力の際にHTML を書き換えられないかを考える。

 コアハックは後のバージョンアップ対応を考えると、あまり現実的ではないので、使うとすればMambots だろう。

 ただし、com_content の出力を直接編集できるイベントは用意されていないので、出力バッファを直接弄る方法が考えられる。

 コンテンツ出力用イベントは下記の4つ。

  • onPrepareContent
  • onAfterDisplayTitle
  • onBeforeDisplayContent
  • onAfterDisplayContent

 出力が始まるのは onPrepareContent の直後なので、ここで出力バッファリングをセットする。

 次に書き換えるHTML だが、コンテンツ本体はHTML を自由にできるので、com_content 自身が出力するHTML が対象となる。

 Joomla-users.jp の文書、「日本の Joomla! ユーザのためのハブサイト」の出力HTML は下記のようになっている。

<table class="contentpaneopen">
	<tr>
		<td class="contentheading" width="100%">
			日本の Joomla! ユーザのためのハブサイト
		</td>
		<td align="right" width="100%" class="buttonheading">
			<a href="http://joomla-users.jp/index2.php?option=com_content&amp;do_pdf=1&amp;id=4" target="_blank" onclick="window.open('http://joomla-users.jp/index2.php?option=com_content&amp;do_pdf=1&amp;id=4','win2','status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no'); return false;" title="PDF">
			<img src="http://joomla-users.jp/templates/rhuk_solarflare_ii/images/pdf_button.png"  alt="PDF" name="PDF" align="middle" border="0" /></a>
		</td>
		<td align="right" width="100%" class="buttonheading">
			<a href="http://joomla-users.jp/index2.php?option=com_content&amp;task=view&amp;id=4&amp;pop=1&amp;page=0&amp;Itemid=1" target="_blank" onclick="window.open('http://joomla-users.jp/index2.php?option=com_content&amp;task=view&amp;id=4&amp;pop=1&amp;page=0&amp;Itemid=1','win2','status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no'); return false;" title="プリント">
			<img src="http://joomla-users.jp/templates/rhuk_solarflare_ii/images/printButton.png"  alt="プリント" name="プリント" align="middle" border="0" /></a>
		</td>
		<td align="right" width="100%" class="buttonheading">
			<a href="http://joomla-users.jp/index2.php?option=com_content&amp;task=emailform&amp;id=4&amp;itemid=1" target="_blank" onclick="window.open('http://joomla-users.jp/index2.php?option=com_content&amp;task=emailform&amp;id=4&amp;itemid=1','win2','status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=400,height=250,directories=no,location=no'); return false;" title="メール">
			<img src="http://joomla-users.jp/templates/rhuk_solarflare_ii/images/emailButton.png"  alt="メール" name="メール" align="middle" border="0" /></a>
		</td>
	</tr>
</table>

<table class="contentpaneopen">
	<tr>
		<td width="70%" align="left" valign="top" colspan="2">
			<span class="small">
				作者 金魚屋・J・龍角
			</span>
			&nbsp;&nbsp;
		</td>
	</tr>
	<tr>
		<td valign="top" colspan="2" class="createdate">
			2008/07/14 月曜日 12:28:16 JST
		</td>
	</tr>
	<tr>
		<td valign="top" colspan="2">
			※ここから本文
		</td>
	</tr>
	<tr>
		<td colspan="2" align="left" class="modifydate">
			最終更新日 ( 2008/07/31 木曜日 23:03:02 JST )
		</td>
	</tr>
</table>

<span class="article_seperator">&nbsp;</span>
<div class="back_button">
	<a href='javascript:history.go(-1)'>
		[ 戻る ]
	</a>
</div>

 まず「PDF」「プリント」「メール」のアイコンは設定で消せるから、とりあえずはいいだろう。

 次にタイトル。td 要素にクラス属性contentheading とあるので、正規表現で何とかなりそうだ。これをまとめてh2 要素かp 要素に置き換える。

 続いて本文。著者名、作成日時、本文、更新日時が出力されている。このへんは細かく書き換える需要は少なそうなので、行を改行に変えてしまおう。</tr> を<br /> に換えて、残りのテーブル要素は全て削除する。

 最後に「戻る」ボタン。class="backbutton" で場所を拾えるとはいえ、よりによってJavaScript でヒストリーバックしてる。携帯では動きようも無いので、JavaScriptリファラURL に置き換えてしまおう。リファラが取れなければ、しょうがないので「戻る」ボタンそのものをなくす。

 これで単体ページはなんとかなりそうだ。

 できあがるHTML は下記のようになる。

<h2>日本の Joomla! ユーザのためのハブサイト</h2>
作者 金魚屋・J・龍角
<br />
2008/07/14 月曜日 12:28:16 JST
<br />
※ここから本文
<br />
最終更新日 ( 2008/07/31 木曜日 23:03:02 JST )
<br />
<a href='/http://joomla-users.jp/'>[ 戻る ]</a>

 これで携帯表示も耐えられそうだ。

 ブログカテゴリ表示も単体表示のHTML とほぼ同じなので、細かいところを消してやればいいだろう。

追記

 Joomla! が標準で出力バッファリングを使用している上、出力のためにob_get_contents() で出力バッファを取得している。

 ob_get_contents は出力バッファのコールバックを実行していない素のバッファを取得するため、単純に出力バッファにコールバックを設定するだけではダメ。

 そこで onAfterDisplayContent で、バッファをフラッシュするコールバック関数を設定した。

 これにより、onPrepareContent で設定した出力バッファコールバックを適用した出力を、Joomla! に渡すことができる。

追記2

 「戻る」ボタンの出力はonAfterDisplayContent() の実行後だった。

 Mambots でコンポーネント出力直後に内容を書き換える機能はないため、対応を考えないといけない。

追記3

 痛々しいことに、ブログカテゴリでのカテゴリ名などの出力は、onPrepareContent の前でcontent マンボットの適用外だった。

とどめ

 結局のところ、Mambot で完璧にどうこうしようというのは無理みたいだ。範疇じゃない箇所で出力されるHTML の多いこと多いこと。

 ただJoomla! で出力バッファを利用しているのはコンポーネント出力のみなので、いっそテンプレートで出力バッファを書き換える仕組みにするのがよさそうだ。

 テンプレートそのものを携帯向けに特化させて、かつmosMainBody() 呼び出し前後で出力バッファリングして書き換えてしまうとか。

 テンプレートごとに機能を実装するのではコストがかかるので、機能のみMambot で提供して、呼び出しをテンプレートでやる、というのがいいかもしれない。