Меняем механизм парсинга документов
С выходом MODX версии 2.7.0, в котором был принят мой PR, появилась возможность менять механизм парсинга документов. В статье я указал один из возможных примеров использования — для сайтов, использующих шаблонизатор Fenom, отключить стандартный парсинг MODX. Это позволит избежать коллизий работы двух парсеров. Давайте на простом примере разберём, как это можно сделать.
Первый вариант — это создать свой кастомный класс. Как это сделать описано в документации. Там несколько шагов — создать класс, настроить поведение в админке, создать процессоры и контроллеры. Задача достаточно трудоёмкая. Но если хочется иметь возможность выбирать тип документа в дереве ресурсов (например, в контекстном меню), то придётся заморочится. В том случае, если нужно всего лишь изменить правила парсинга на сайте для всех документов, рассмотрим упрощенный вариант.
Давайте в плагине при загрузке документа просто подменять класс. Всего несколько строчек, которые меняют всё! Но перед созданием плагина давайте создадим наш новый класс. Назовём его fenomDocument
. Файл можно разместить в любом месте. В нашем случае положим его в core/classes/fenomdocument.php
.
<?php class fenomDocument extends modResource { /** * Overrides modResource::__construct to set the class key for this Resource type * @param xPDO $xpdo A reference to the xPDO|modX instance */ function __construct(& $xpdo) { parent :: __construct($xpdo); $this->set('class_key','fenomDocument'); } public function parseContent($data = array()) { $oldResource = $this->xpdo->resource; $this->xpdo->resource = $this; if (!empty($data)) { $scope = $this->xpdo->toPlaceholders($data, '', '.', true); } $this->_output = $this->_content; $this->_output = $this->xpdo->getParser()->pdoTools->fenom($this->_output, $this->xpdo->placeholders); $this->xpdo->resource = $oldResource; if (isset($scope['keys'])) $this->xpdo->unsetPlaceholders($scope['keys']); if (isset($scope['restore'])) $this->xpdo->toPlaceholders($scope['restore']); $this->_processed= true; return $this->_output; } } /** * Class fenomDocument_mysql */ class fenomDocument_mysql extends fenomDocument {}
Для простоты сюда же добавил класс для mySql. Чтобы обойтись одним инклюдом.
Теперь нужно подключить класс. Создаём плагин fenomDocument
и отмечаем для него события «OnWebPageInit» и «OnLoadWebDocument».
<?php switch ($modx->event->name) { case 'OnWebPageInit': include_once MODX_CORE_PATH . 'classes/fenomdocument.php'; // Добавляем в карту классов. $modx->map['fenomDocument'] = [ 'extends' => 'modResource', 'fields' => [], 'fieldMeta' => [], ]; break; case 'OnLoadWebDocument': $data = $modx->resource->toArray(); $modx->resource = $modx->newObject('fenomDocument'); $modx->resource->fromArray($data, '', true, true); /* // Если нужно работать только с ресурсами класса modDocument, то используем соответствующее условие. if ($modx->resource instanceof modDocument) { .... } */ break; }
Пришла очередь протестировать полученное. Создайте страницу с тегами MODX и Fenom и откройте её на фронте. В результате должно получится, что первые остались нетронутыми, а вторые замечательно распарсились. И всё работает по правилам шаблонизатора — контент парсится один раз. А значит и пресловутый тег ignore будет работать на любом уровне вложенности.
Тут надо ещё отметить, что данный механизм парсинга предназначен только для контента ресурса. Т.е. шаблон MODX не учитывается. Чтобы оставить парсинг шаблона, раскомментируйте код в методе fenomDocument::prepare()
. Правда в этом случае парсить шаблон будет парсер MODX. Ну а в следующей статье мы рассмотрим возможность работать с шаблонами Fenom.
Данное решение работает так:
- Если есть шаблон, то парсятся только кэшируемые теги MODX. Если есть теги Fenom, то они будут распарсены на следующем шаге.
- В подготовленном контенте ресурса парсятся только теги Fenom.
Заключение
Описанное выше решение является демонстрацией возможностей. Аналогично можно реализовать парсинг и для парсеров Smarty и Twig.
Кстати, не все знают, что админка использует шаблонизатор Smarty и в ней не работает парсер MODX.
Update 01.12.2018
Чтобы не путаться, оставил вариант с парсингом шаблона. Таким образом, если в шаблоне указать кэшируемые теги MODX, они будут распарсены. А следующей статье откажемся и от шаблонов MODX, а соответственно и полностью от его парсера.
Update 05.12.2018
С прискорбием сообщаю, что всё-таки специфика MODX не позволяет использовать только парсер Fenom. Если с чанками и сниппетами ещё можно как-то работать (в компилированный файл попадает результат modX::getChunk()
и modX::runSnippet()
), то конструкции типа $_modx->resource.content
так и компилируются. И, соответственно, выводится только контент ресурса без обработки парсером. А если дополнительно парсить такие конструкции, то вернёмся опять к тому, что было. Вот такой получается результат исследований.
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
И ещё вопрос. Как быть с документами имеющими отличный от modResource, например с ресурсами Минишопа?
В примере я специально указал класс modDocument для демонстрации возможности фильтрации ресурсов. Для полноценного отказа от парсера MODX фильтрацию нужно убрать. Т.е. обрабатывать все документы без исключения.
Как вы используете content ресурса?
Даже лучше стандартного поведения, ведь контент менеджер не сломает ничего, когда решит написать фигурные скобки.
Единственное место где я использую вызов сниппета прямо в контенте это страница sitemap, но можно просто создать новый шаблон.
Правда это не спасёт от ошибок фенома.
Вообще, из MODX нужно выпиливать родной парсер. Его практически не развивали. Его функционал крайне слабенький. Сейчас есть несколько мощных шаблонизаторов, выбирай не хочу. Но выпилить его в ближайшее время вряд ли получится. А пользоваться описанными выше костылям не внушает серьёзности системе. Выкрутиться из положения — да. Но для нормальной работы этого мало.