(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

MODX Revolution - пара костылей для необычных ситуаций

Источник: habrahabr
Agel_Nash

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

  1. Разбор бэкенда
  2. Углубление в настройки
  3. Работа с вложенными чанками
  4. Наблюдаем за работой парсера
  5. Мощный кеш



Удаление параметра из набора параметров


Создаем набор параметров. В него добавляем Х параметров, а потом понимаем, что мы разошлись. Пытаемся найти кнопку удалить… 

В общем у меня ничего не вышло. Пришлось искать другой способ удаления параметра.
Решение проблемы: открываем на редактирование ненужный параметр и полностью копируем все данные другого нужного параметра (якобы пытаясь перезаписать старый параметр новыми данными).
Следствие: Можем перезаписать значение нужного параметра.

Значения ключей в настройках контекстов


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

Как вы думаете, какой результат мы увидим во front-end? Правильно, просто Крутые.
Решение проблемы: вместо скобок использовать специальные символы.
А что делать тем, кто у кого используется 1 шаблон на нескольких контекстах и желает в качестве ключа указать некий набор параметров для JS кода? Там специальные символы не помогут и одним чанком не обойтись.
Тут решений уже два
  • Первое решение: создать свой сниппет и в зависимости от контекста отдавать нужный чанк посредством getChunk.
  • Второе решение: Для каждого контекста создать свой чанк и в шаблоне вместо ключа прописать [[$name_[[*context_key]]]]. Но как бы там нибыло, данная запись выглядит вырвиглазно… 


Работа с вложенными чанками


В 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? Это уже на несколько МБ тянет. А если новости добавляются каждый день?

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 05.10.2012 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
ABViewer Standart пользовательская
ABBYY Lingvo x6 Европейская Домашняя версия, электронный ключ
TeeBI for RAD Studio Suite with source code single license
Microsoft Office 365 Бизнес. Подписка на 1 рабочее место на 1 год
EMS SQL Management Studio for InterBase/Firebird (Business) + 1 Year Maintenance
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
Программирование на Visual С++
ЕRP-Форум. Творческие дискуссии о системах автоматизации
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100