4月からPowerCMS X導入の案件に携わっています。色々な要望がありPHPでプラグインを書いて実装を行いました、今日はその中から「エディタに書くコンテンツをログイン状態に応じて出し分けしたい」という要望についてご紹介したいと思います。
要望の内容
記事やページ、自作のモデルにリッチテキストエディタを用意してコンテンツを書くことは多いのではないかと思います。その際、会員サイトにログインしている場合はAの内容を、そうでない場合はBの内容を出したいというものでした。ログインしている場合・していない場合に応じてカラムが用意してあればmt:iflogin
を使用して分岐をすれば良いのですが、リッチテキストエディタの場合はどのようにすればよいでしょうか。
独自の要素(タグ)を作成する
どのように対応するかを検討する中で、以前Web Componentsについて研究した際に独自の要素(タグ)を作成したことを思い出しました。そこでTinyMCEでも独自の要素が使えないかを調べたところ、「custom_elements」の設定により独自の要素が利用できることが分かりました。そこでx-iflogin
とx-ifnotlogin
要素を作成することにしました。
TinyMCEの設定
TinyMCEプラグインを有効にし、マニュアルに沿って設定を記述します。「書式」プルダウンで要素が利用できるような設定も記述します。
custom_elements: 'x-iflogin,x-ifnotlogin',
extended_valid_elements: 'x-iflogin,x-ifnotlogin',
style_formats: [
{
title: 'Members',
items: [
{ title: 'iflogin', block: 'x-iflogin', wrapper: true },
{ title: 'ifnotlogin', block: 'x-ifnotlogin', wrapper: true }
]
}
],
end_container_on_empty_block: true,
編集画面
編集画面にはログインしている場合のコンテンツとログインしていない場合のコンテンツをx-iflogin
とx-ifnotlogin
要素を利用して記述しました。エディタのCSSで色分けをしたりx-iflogin
の表示を追加するなどしています。また「書式」プルダウンメニューにx-iflogin
とx-ifnotlogin
が表示されており、容易に要素を設定できるように工夫しています。
x-iflogin::before,
x-iflogin::after {
position: relative;
display: inline-block;
padding: 2px;
background-color: #de4040;
color: #fff;
font-size: 7px;
}
x-iflogin::before {
content: "iflogin";
}
x-iflogin {
display: block;
background-color: #fff3f3;
}
x-iflogin::after {
content: "/iflogin";
}
x-ifnotlogin::before,
x-ifnotlogin::after {
position: relative;
display: inline-block;
padding: 2px;
background-color: #6cbb26;
color: #fff;
font-size: 7px;
}
x-ifnotlogin::before {
content: "ifnotlogin";
}
x-ifnotlogin {
display: block;
background-color: #edfce0;
}
x-ifnotlogin::after {
content: "/ifnotlogin";
}
プラグイン
ログイン状態に応じてx-iflogin
の内容を削除してx-ifnotlogin
要素の内容を表示したり、その逆の処理をしたりするモディファイアのコードを記述しました。PHPなので割とスラスラ書ける印象です。
<?php
require_once LIB_DIR . 'Prototype' . DS . 'class.PTPlugin.php';
class EnhancedEditor extends PTPlugin
{
public function __construct()
{
parent::__construct();
}
public function modifier_process_xlogin($str, $args, $ctx)
{
$members = $ctx->app->component('Members');
$member = $members->member($ctx->app);
if ($member) {
// ログインしている場合
// x-ifloginの内容は生き、x-ifnotloginの内容は削除
$remove_block = 'x-ifnotlogin';
$reserve_block = 'x-iflogin';
} else {
// ログインしていない場合
// x-ifloginの内容は削除、x-ifnotloginの内容は生き
$remove_block = 'x-iflogin';
$reserve_block = 'x-ifnotlogin';
}
$doc = new DOMDocument();
$intro = '<!DOCTYPE html><html><head><meta charset="UTF-8"><body>';
$outro = '</body></html>';
$doc->loadHTML($intro . $str . $outro);
$nodes_delete = array();
foreach ($doc->getElementsByTagName($remove_block) as $delete) {
$nodes_delete[] = $delete;
}
foreach ($nodes_delete as $node) {
$node->parentNode->removeChild($node);
}
$html = $doc->saveHTML($doc->documentElement);
$html = preg_replace("/<\/?${reserve_block}>/", '', $html);
$html = preg_replace('/<html>\n?.+\n?<body>/', '', $html);
$html = preg_replace('/<\/body>\n?<\/html>/', '', $html);
return $html;
}
}
コンテンツ表示例
文章と文章の間にある枠線囲み内の文章がログイン状態に応じて変化します。
まずはログインしていない場合の表示例です。「【会員限定情報あり】会員になると会員限定の情報が閲覧できます。」と表示されます。
次にログインしている場合の表示例です。「会員のみなさまにはテンプレート設計の無料セミナーにご招待します。」と表示されます。
まとめ
今回は独自の要素を作成するというアイデアをPHPを用いてプラグインを書くことにより上手く実現することができました。案件ではその他にも検索をカスタマイズしたり、管理画面をカスタマイズしたりもしました。PHPとPADOの知識を身につけることで仕事の幅が広がるなというのを実感しているこの頃です。