MODX конечно крутая CMF, но порой сталиваешся с такими мелочами, которые напрягают. Я не буду в этом топике плакаться какие все вокруг плохие, а я такой хороший. Возьмем, например, ветку Revolution и препарируем ее. А чтобы вы не потеряли интерес к этой заметке, вот небольшой план статьи:
Создаем набор параметров. В него добавляем Х параметров, а потом понимаем, что мы разошлись. Пытаемся найти кнопку удалить…

В общем у меня ничего не вышло. Пришлось искать другой способ удаления параметра.
Решение проблемы: открываем на редактирование ненужный параметр и полностью копируем все данные другого нужного параметра (якобы пытаясь перезаписать старый параметр новыми данными).
Следствие: Можем перезаписать значение нужного параметра.
Смоделируем такую ситуацию: несколько контекстов, к каждому контексту привязаны свои настройки.
Если в админке несколько сайтов, то как правило в настройках контекста переопределяют такой ключик, как site_name. А теперь представьте, ваша фирма всегда позиционировала свое название как Крутые{Перцы}.

Как вы думаете, какой результат мы увидим во front-end? Правильно, просто Крутые.
Решение проблемы: вместо скобок использовать специальные символы.
А что делать тем, кто у кого используется 1 шаблон на нескольких контекстах и желает в качестве ключа указать некий набор параметров для JS кода? Там специальные символы не помогут и одним чанком не обойтись.
Тут решений уже два
В MODX еще с давних пор есть такая функция, как
А теперь давайте создадим простой
установим phpthumbof и создадим
Сделаем вызов этого всего на странице примерно так:
Но вот незадача, при первом вызове в сниппет phpthumbof приходит строка [[+item]] и только при всех последующих уже распарсеный плэйсхолдер

Решение: Хранить такие проблемные чанки в файлах. Т.е. поставить галочку статичный и выбрать файл

Еще одно решение от bezumkin: Заменить parseChunk на getChunk.
Эксперимент проведем следующим образом: создадим новый документ с шаблоном blank. Содержимое и все остальное оставим пустым. Проверим, что стоит галочка кешировать.
перед строкой
Ну и открываем в браузере нашу страницу. о0! число 1..2..3 Спрашивается какого мать вашу… Пустая страница. Что там парсить? Смотрим внимательно исходник
Таким образом даже на пустой странице мы вызываем 3 раза одно и тоже событие. Мне страшно подумать, что будет с теми сайтами, у которых еще на это событие повешан какой-то код.
artdevue для эксперимента проверил сколько раз будет выполняться данная функция при различных условиях. таким образом мы имеем следующую табличку.
На одном из рабочих сайтов открыл я папку с кешем и чуть со стула не упал. 1 страница в кеше занимает от 50 до 200 КБ. Нет, это может конечно и нормально, но кеш обновляется при каждом изменении документов. Обновил 1 документ — все закешированные страницы удалились. А если 100 страниц? 1000? Это уже на несколько МБ тянет. А если новости добавляются каждый день?
P.S. Переименовал топик, чтобы выглядело менее плаксиво и вызывающе
- Разбор бэкенда
- Углубление в настройки
- Работа с вложенными чанками
- Наблюдаем за работой парсера
- Мощный кеш
Удаление параметра из набора параметров
Создаем набор параметров. В него добавляем Х параметров, а потом понимаем, что мы разошлись. Пытаемся найти кнопку удалить…

В общем у меня ничего не вышло. Пришлось искать другой способ удаления параметра.
Решение проблемы: открываем на редактирование ненужный параметр и полностью копируем все данные другого нужного параметра (якобы пытаясь перезаписать старый параметр новыми данными).
Следствие: Можем перезаписать значение нужного параметра.
Значения ключей в настройках контекстов
Смоделируем такую ситуацию: несколько контекстов, к каждому контексту привязаны свои настройки.
Если в админке несколько сайтов, то как правило в настройках контекста переопределяют такой ключик, как site_name. А теперь представьте, ваша фирма всегда позиционировала свое название как Крутые{Перцы}.

Как вы думаете, какой результат мы увидим во front-end? Правильно, просто Крутые.
Решение проблемы: вместо скобок использовать специальные символы.
А что делать тем, кто у кого используется 1 шаблон на нескольких контекстах и желает в качестве ключа указать некий набор параметров для JS кода? Там специальные символы не помогут и одним чанком не обойтись.
Тут решений уже два
- Первое решение: создать свой сниппет и в зависимости от контекста отдавать нужный чанк посредством getChunk.
- Второе решение: Для каждого контекста создать свой чанк и в шаблоне вместо ключа прописать [[$name_[[*context_key]]]]. Но как бы там нибыло, данная запись выглядит вырвиглазно… Спасибо artdevue за данное решение.
Работа с вложенными чанками
В MODX еще с давних пор есть такая функция, как
getChunk
(от нее, например, зависит parseChunk).
public function getChunk($chunkName, array $properties= array ()) { $output= ''; if (array_key_exists($chunkName, $this->sourceCache['modChunk'])) { $chunk = $this->newObject('modChunk'); $chunk->fromArray($this->sourceCache['modChunk'][$chunkName]['fields'], '', true, true); $chunk->setPolicies($this->sourceCache['modChunk'][$chunkName]['policies']); } else { $chunk= $this->getObject('modChunk', array ('name' => $chunkName), true); if (!empty($chunk) || $chunk === '0') { $this->sourceCache['modChunk'][$chunkName]= array ( 'fields' => $chunk->toArray(), 'policies' => $chunk->getPolicies() ); } } if (!empty($chunk) || $chunk === '0') { $chunk->setCacheable(false); $output= $chunk->process($properties); } return $output; }
А теперь давайте создадим простой
сниппет
<?php ini_set("display_errors",1); $data=''; $phs=isset($phs)?explode(",",$phs):array(); if(isset($tpl,$phs) && $tpl!='' && count($phs)>0){ foreach($phs as $item){ $data.=$modx->parseChunk($tpl,array('item'=>$item,'time'=>time())); } } return $data;
установим phpthumbof и создадим
чанк
<p><b>[[+time]]</b>: [[+item]] - [[!phpthumbof? &input=`[[+item]]` &options=`&h=150&f=jpg`]]</p>
Сделаем вызов этого всего на странице примерно так:
[[!test? &tpl=`test` &phs=`/assets/1.jpg,/assets/2.jpg`]]Но вот незадача, при первом вызове в сниппет phpthumbof приходит строка [[+item]] и только при всех последующих уже распарсеный плэйсхолдер

Решение: Хранить такие проблемные чанки в файлах. Т.е. поставить галочку статичный и выбрать файл

Еще одно решение от bezumkin: Заменить parseChunk на getChunk.
Наблюдаем за работой парсера
Эксперимент проведем следующим образом: создадим новый документ с шаблоном blank. Содержимое и все остальное оставим пустым. Проверим, что стоит галочка кешировать.
Теперь откроем функцию processElementTags из файла /core/mode/modx/modparser.class.php
public function processElementTags($parentTag, & $content, $processUncacheable= false, $removeUnprocessed= false, $prefix= "[[", $suffix= "]]", $tokens= array (), $depth= 0) { $this->_processingTag = true; $this->_processingUncacheable = (boolean) $processUncacheable; $this->_removingUnprocessed = (boolean) $removeUnprocessed; $depth = $depth > 0 ? $depth - 1 : 0; $processed= 0; $tags= array (); /* invoke OnParseDocument event */ $this->modx->documentOutput = $content; $this->modx->invokeEvent('OnParseDocument', array('content' => &$content)); $content = $this->modx->documentOutput; unset($this->modx->documentOutput); if ($collected= $this->collectElementTags($content, $tags, $prefix, $suffix, $tokens)) { $tagMap= array (); foreach ($tags as $tag) { $token= substr($tag[1], 0, 1); if (!$processUncacheable && $token === '!') { if ($removeUnprocessed) { $tagMap[$tag[0]]= ''; } } elseif (!empty ($tokens) && !in_array($token, $tokens)) { $collected--; continue; } if ($tag[0] === $parentTag) { $tagMap[$tag[0]]= ''; $processed++; continue; } $tagOutput= $this->processTag($tag, $processUncacheable); if (($tagOutput === null || $tagOutput === false) && $removeUnprocessed) { $tagMap[$tag[0]]= ''; $processed++; } elseif ($tagOutput !== null && $tagOutput !== false) { $tagMap[$tag[0]]= $tagOutput; if ($tag[0] !== $tagOutput) $processed++; } } $this->mergeTagOutput($tagMap, $content); if ($depth > 0) { $processed+= $this->processElementTags($parentTag, $content, $processUncacheable, $removeUnprocessed, $prefix, $suffix, $tokens, $depth); } } $this->_processingTag = false; return $processed; }
перед строкой
добавим$this->_processingTag = true;
static $test; echo ++$test."<br />";
Ну и открываем в браузере нашу страницу. о0! число 1..2..3 Спрашивается какого мать вашу… Пустая страница. Что там парсить? Смотрим внимательно исходник
$this->modx->invokeEvent('OnParseDocument', array('content' => &$content));
Таким образом даже на пустой странице мы вызываем 3 раза одно и тоже событие. Мне страшно подумать, что будет с теми сайтами, у которых еще на это событие повешан какой-то код.
artdevue для эксперимента проверил сколько раз будет выполняться данная функция при различных условиях. таким образом мы имеем следующую табличку.
| Условие | Итераций |
|---|---|
| [[snippet]] | 2 |
| {{$chunk}} | 2 |
| Пустая страница | 3 |
| [[num?input=`1000`]] | 5 |
| [[*pagetitle:num]] | 6 |
| [[num?input=`[[*pagetitle]]`]] | 7 |
| Несуществующий сниппет | 23 |
| Несуществующий чанк | 23 |
Мощный кеш
На одном из рабочих сайтов открыл я папку с кешем и чуть со стула не упал. 1 страница в кеше занимает от 50 до 200 КБ. Нет, это может конечно и нормально, но кеш обновляется при каждом изменении документов. Обновил 1 документ — все закешированные страницы удалились. А если 100 страниц? 1000? Это уже на несколько МБ тянет. А если новости добавляются каждый день?
P.S. Переименовал топик, чтобы выглядело менее плаксиво и вызывающе
