MODxのPHxで文字列の置換を行うカスタムモディファイア

MODxのプラグイン、PHxで正規表現による文字列の置換を行うためのカスタムモディファイアを作成してみました。

PHxは、MODxのプレイスホルダやテンプレート変数、セッティングタグの内容に対して、加工や条件分岐を行える非常に柔軟かつ強力なプラグインです。専用のスニペットを作成することで、カスタムモディファイアとしてPHxの機能を拡張することができます。PHxについては、MEGUさんの「Let's enjoy MODx|PHx 2.1.2 (Placeholders Xtended)」に日本語の詳しい解説がありますので、そちらをご覧ください。

内蔵のモディファイアの他に色々なカスタムモディファイアが公開されていますが、ちょっとした加工に正規表現を使えた方が便利だと思い、このreplaceモディファイアを作成しました。

PHx:replaceモディファイア
<?php
if (strlen($options) > 0 &&
    preg_match('/^(.)((?>\\\\.|[^\1])+)\1((?>\\\\.|[^\1])*)\1([^\1]*)$/', $options, $matches)) {
        $pattern = $matches[1] . $matches[2] . $matches[1] . $matches[4];
        $replacement = str_replace('\\' . $matches[1] , $matches[1], $matches[3]);
        $output = preg_replace($pattern, $replacement, $output);
}

return $output;
?>

インストールは、「phx:replace」というような名前でスニペットを新規作成し、上記のコードをコピー&ペーストして保存するだけです。

PHxのモディファイアは1回につき1つの値しか指定できないため、Perl風の表記方法を正規表現でパースしてから置換するようにしています。replaceモディファイアの値は次のような書式で記述します。

/検索パターン/置換文字列/パターン修飾子

モディファイアの値の一文字目の文字が区切り文字になります。区切り文字自身を記述する場合は\/のように\でエスケープします。\自身を記述する場合は\\です。

具体的には次のような感じで使います。

<!-- 整数が入ったテンプレート変数「price」を3桁ごとにカンマで区切る -->
<!-- 置換前: 「10000」  置換後: 「10,000」 -->
[*price:replace=`/(\d)(?=(\d\d\d)+(?!\d))/$1,/`*]
<!-- コンテンツ中のclass属性値「uri」のみを持つspan要素をa要素に変換 -->
<!- 変換前: 「<span class="uri">http://dxd8.com</span>」
    変換後: 「<a href="http://dxd8.com">http://dxd8.com</a>」 -->
[*content:replace=`!<span\s+class\s*=\s*["']\s*uri\s*["']\s*>\s*(.+?)\s*</span\s*>!<a href="$1">$1</a>!`*]

PHxのモディファイアの値にはブラケットは使えませんでした。ブラケットを使わない書き方に直すか、replaceモディファイアを修正しないとダメですね。

PHxのモディファイアは、直前のモディファイアが返す文字列をそのまま返すため、チェーン状に次々と加工を行えます。正規表現による文字列の置換処理を繰り返して行えるため、(それが良いかは別として)複雑な加工もこのreplaceモディファイアだけで大体できてしまうと思います。

<!-- 「price」が1000未満なら「特価 」を追加 -->
<!-- 置換前: 「900」  置換後: 「特価 900」 -->
[*price:replace=`/(\d)(?=(\d\d\d)+(?!\d))/$1,/`:replace=`/^(\d{1,3})$/特価 $1/`*]円

検索パターン、置換文字列の中にMODxのタグを記述することで再帰的な処理が行えますが、検索パターン、置換文字列の一部としてMODxのタグと同じ書式の文字列を使うことはできません。エスケープできるようにしようかとも思ったのですが、今のところそのままにしています。

MODx自身にタグをエスケープするための書式があったような気がするのですが、ちょっと思い出せません。以前、「スニペットのオプションに使えない文字」の方法で回避したことがあるので、やっぱり気のせいかもです。

現在は、モディファイアの値として検索パターン、置換文字列を直に指定するようになっていますが、他のモディファイアや処理パターンを登録したチャンクを指定できるようにすれば、複雑な処理を一括で簡単に行える汎用フィルタモディファイア(?)のようなものができそうですね。

コメント (3)

はじめまして
MODxの修行中でして、いろいろ勉強させていただいてます。
便利にカスタムモディファイア使用させていただいてます。
PHP知識がないので、教えていただきたいのですが、PHxでmath= で計算式での小数点以下を切り捨てしたいのですが、アドバイスいただけませんでしょうか・・やりたいことはテンプレート変数を使った税計算です。

としさん、はじめまして。
モディファイアを使った簡単な方法ですと、値を切り捨てるための「floor」というモディファイアを作成するのはどうでしょうか?
「PHx:floor」というスニペットを <?php return floor($output); ?> という内容で作ります。そうすれば、あとは [*tv:math=`? * 1.1`:floor*] という感じで使えます。ちなみに、計算式の中でTVタグがそのまま使えるので [*tv:math=`? * [*tv2*]`:floor*] のようなこともできると思います。
(floorをround、ceil等に変えれば、四捨五入や切り上げもできます。)

Phizeさま
すばやい回答ありがとうございます^^感謝!です。
関数をどう組み込めばと悩んでいたところで、すっきりしました。またご指導よろしくお願いします。 

コメントフォーム

トラックバック (0)

この記事へのトラックバックはまだありません。

この記事のトラックバックURI
http://dxd8.com/archives/97/trackback/
この記事のURI
http://dxd8.com/archives/97/