MODX Revolutionに新しいタグを追加します

このトピックでは、このCMSに新しいタグを追加するMODX Revolutionのプラグインを作成した経験について説明します。 開発者が自分のサイトのコンテンツコンテンツまたはテンプレートとチャンクでタグを使用できることを思い出させてください。 たとえば、 [[* pagetitle]]タグはMODXパーサーによって処理され、ユーザーがいるページのタイトルを返します。



タグの広範なリストの中で、もう1つ欠けていました。選択したリソースのフィールドを表示することです。 これを行うには、MODXリポジトリからgetResourceFieldスニペットをダウンロードしてインストールする必要がありました。 このソリューションがCMSの基本的な配信に含まれていないという不便さに加えて、私の考えでは、名前が長すぎます。パラメーター名を混同しないようにRTFMを開いておく必要があることは言うまでもありません。 したがって、 fastFieldプラグインを作成しました。これについては後で説明します。



最初に、プラグインをハングさせるイベントを決定する必要がありました。 MODXシステムに慣れていない人のために、ここでのプラグインは、事前定義されたイベントで呼び出されるアドオンと呼ばれることに注意してください。 デフォルトで提供されるシステムイベントの大規模なリストから、modParserクラス(file core / model / modx / modparser.class.php)のprocessElementTags()メソッドでMODXパーサーで呼び出されるため、OnParseDocumentイベントのみが適切であることが判明しました。 その後、イベントはすべて存在しないものとして切り取られるため、タグ付きのコンテンツを受信できなくなります。

プラグインの初期バージョンは非常にシンプルでした:



$content = $modx->documentOutput; $pattern = '@\[\[#(\d+)\.(.+?)\]\]@si'; if (preg_match($pattern, $content, $matches) > 0) { $tag = $matches[0]; $resource_id = $matches[1]; $resource_field = explode('.', $matches[2]); $resource = $modx->getObject('modResource', $resource_id); if (count($resource_field) == 1) { $value = $resource->get($resource_field[0]); } else { if ($resource_field[0] == 'tv' && isset($resource_field[1])) { $value = $resource->getTVValue($resource_field[1]); } elseif (in_array($resource_field[0], array('properties', 'property', 'prop'))) { $value = $resource->getProperty($resource_field[2], $resource_field[1]); } else { $value = ''; } } $modx->documentOutput = str_replace($tag, $value, $content); }
      
      





タスクは、[[#10.pagetitle]]、[[#10.tv.MyTV]]という形式のタグを処理することでした。 原則として、問題は解決しましたが、 I / Oフィルターをフィールドに適用することは不可能でした。

したがって、パーサーがタグを処理するときに何をするかをよりよく理解する必要がありました。 そして彼は次のことをします。

関数を使用してコンテンツ内のすべてのタグを収集します

 public function collectElementTags($origContent, array &$matches, $prefix= '[[', $suffix= ']]')
      
      





さらに、タグは2つの要素(外部タグと内部タグ)の配列の形式で返されます。 新しいタグにはタグのすべての属性があるため、この関数はそれも返します。 次に、$ tagMap配列が作成されます。この配列には、tag => processed tagという形式のstr_replace関数の置換のリストが含まれています。 各タグを処理するときに、パーサー関数が呼び出されます

 public function processTag($tag, $processUncacheable = true)
      
      





タグのコンテンツが複数の部分に分割されます:トークン(特定のタイプのタグを示す記号、たとえば、リソースフィールドの*またはリンクの〜、この場合はポンド記号#)、名前(またはタグ本文、たとえば[ [* pagetitle]])、フィルター(:ucaseなど)およびパラメーター(スニペットタグまたはその他のパラメーター)。 トークンは、タグを処理するために呼び出される特定のタグクラスを決定します。 それらはすべて、抽象modTagクラスの子孫です。 したがって、新しいタグを作成するには、新しいクラスmodResourceFieldTagを作成します。 すべてのタグクラスは、process()およびgetContent()メソッドをオーバーライドしました。 同時に、新しいタグはリソースフィールドタグに非常に似ており、modFieldTagクラスから派生させて、そのprocess()メソッドを残しました。 起こったことは次のとおりです。



 class modResourceFieldTag extends modFieldTag { /** * Overrides modTag::__construct to set the Field Tag token * {@inheritdoc} */ function __construct(modX & $modx) { parent :: __construct($modx); $this->setToken('#'); } /** * Get the raw source content of the field. * * {@inheritdoc} */ public function getContent(array $options = array()) { if (!$this->isCacheable() || !is_string($this->_content) || $this->_content === '') { if (isset($options['content']) && !empty($options['content'])) { $this->_content = $options['content']; } else { $tag = explode('.', $this->get('name')); $tagLength = count($tag); // for processing tags in resource_id place ([[#[[+id]].pagetitle]]) $tags = array(); if ($collected= $this->modx->parser->collectElementTags($tag[0], $tags)) { $tag[0] = $this->modx->parser->processTag($tags[0], $this->modx->parser->isProcessingUncacheable()); } if (is_numeric($tag[0])) { $resource = $this->modx->getObject('modResource', $tag[0]); if ($resource) { if ($tagLength == 2) { if ($tag[1] == 'content') { $this->_content = $resource->getContent($options); } else { $this->_content = $resource->get($tag[1]); } } else { if (($tag[1] == 'tv') && ($tagLength == 3)) { $this->_content = $resource->getTVValue($tag[2]); } elseif (in_array($tag[1], array('properties', 'property', 'prop')) && ($tagLength == 4)) { $this->_content = $resource->getProperty($tag[3], $tag[2]); } else { $this->_content = ''; } } } else { $this->_content = ''; } } } } return $this->_content; } }
      
      





リソース識別子のプレースホルダー([[#[[+ id]]。Pagetitle]]など)でタグが呼び出された場合に対処するために、タグのこの部分を追加で処理します。

 $tags = array(); if ($collected= $this->modx->parser->collectElementTags($tag[0], $tags)) { $tag[0] = $this->modx->parser->processTag($tags[0], $this->modx->parser->isProcessingUncacheable()); }
      
      





フィルターで呼び出すことができるタグは、イベント後にパーサーによって処理されます。



これで、実際にはfastFieldプラグインでタグデータの処理を呼び出すことができます。

 switch ($modx->event->name) { case 'OnParseDocument': $content = $modx->documentOutput; $tags= array (); if ($collected= $modx->parser->collectElementTags($content, $tags, '[[', ']]', array('#'))) { $tagMap= array (); foreach ($tags as $tag) { $token = substr($tag[1], 0, 1); if ($token == '#') { include_once $modx->getOption('core_path') . 'components/fastfield/model/fastfield/fastfield.php'; $tagParts= xPDO :: escSplit('?', $tag[1], '`', 2); $tagName= substr(trim($tagParts[0]), 1); $tagPropString= null; if (isset ($tagParts[1])) { $tagPropString= trim($tagParts[1]); } $element= new modResourceFieldTag($modx); $element->set('name', $tagName); $element->setTag(''); $element->setCacheable(false); $tagMap[$tag[0]] = $element->process($tagPropString); } } $modx->parser->mergeTagOutput($tagMap, $content); $modx->documentOutput = $content; } break; }
      
      







この記事が読者が独自のタグを作成するためのガイドとして役立つことを願っています。 コードは完璧ではないかもしれませんが、この素晴らしいCMS / CMFを使ったさらなる実験の準備として役立ちます。



プラグインのソースコードはGitHubで入手できます



All Articles