pdoTools::getChunk -обработка прочих прейсхолдеров

Вопрос такой. pdoTools::getChunk() самостоятельно обрабатывает только те плейсхолдеры, которые указаны вторым параметром? Все остальные плейсхолдеры (за исключением лексикона) обрабатывает стандартный парсер modx?

И для того, чтобы pdoTools::getChunk() самостоятельно обработал все плейсхолдеры modx (не передавая их стандартному парсеру), необходимо:
а) либо вторым параметром передавать что-то вроде array_merge($placeholders, $modx->placeholders);
б) либо перегрузить метод pdoTools::getChunk(), добавив обработку плейсхолдеров modx, не указанных вторым параметром

Так?
Cyrax_02
08 декабря 2013, 15:11
modx.pro
2
5 062
0

Комментарии: 18

Василий Наумкин
08 декабря 2013, 20:49
0
Да.

Можно еще использовать fastMode (третий параметр) — тогда тоже будет использован modX::placeholders.
    Cyrax_02
    10 декабря 2013, 20:50
    0
    Режим fastMode не использую в сабжевых целях, т.к. не обрабатываются вложенные чанки и прочие теги modx.

    Провёл тест суммарного времени выполнения методов pdoTools::getChunk() на странице с большим числом вызовов чанков. Результаты получились такие:
    1) $modx->pdoTools->getChunk($chunkName, array_merge($placeholders, $modx->placeholders), false); // время: X сек
    2) $modx->pdoTools->getChunk($chunkName, $placeholders, false); // время: 0.5X сек
    3) $modx->pdoTools->getChunk($chunkName, $placeholders, true); // время: 0.2X сек

    То, что 2-й вариант отработал вдвое быстрее 1-го варианта, можно объяснить тем, что у меня в большинстве чанков размещены только те плейхолдеры, которые передаются вторым параметром в pdoTools::getChunk():
    — в первом варианте для каждого вызова pdoTools::getChunk() идёт вызов метода str_replace для большого числа плейсхолдеров (из которых в чанке содержатся только некоторые), но при этом до стандартного парсера modx дело не доходит;
    — во 2-м варианте метод str_replace вызывается только для малого числа плейсхолдеров, которые заведомо присутствуют в чанках, при этом стандартный парсер modx вызывается только для единичных чанков, в которых присутствуют плейсхолдеры, не переданные вторым параметром в pdoTools::getChunk().
    Таким образом, вызовы st_replace для большого числа плейсхолдеров по времени вдвое перевешивают редкие вызовы стандартного парсера modx.

    Но не пойму я, почему 3-й вариант (fastMode c «ручной» обработкой всех плейсхолдеров из $modx->placeholders) выполняется в 5 раз быстрее, чем 1-й вариант. Ведь в обоих этих случаях выполняется «ручная» обработка всех плейсхолдеров (переданных 2-м параметром + $modx->placeholders) и в обоих случаях до стандартного парсера modx дело не доходит.
      Василий Наумкин
      10 декабря 2013, 21:03
      0
      Метод fastProcess не использует makePlaceholders и не генерирует большой массив плейсхолдеры-значения, как в первом случае. Чем больше массив, тем дольше подстановка.

      В третьем вызове идёт точечная проверка ключей в modX::placeholders — это гораздо быстрее.

      Можно попробовать сделать двойную обработку:
      // обработка всех переданных плейсхолдеров с условиями
      $html = $modx->pdoTools->getChunk($chunkName, $placeholders, false);
      // подстановка из modX::placeholders
      $html = $modx->pdoTools->fastProcess($html);
        Cyrax_02
        11 декабря 2013, 12:11
        0
        В третьем вызове идёт точечная проверка ключей в modX::placeholders — это гораздо быстрее.

        Хотел было спросить, почему такой же «точечный» метод (на основе collectElementTags) не реализован в отношении плейсхолдеров, передаваемых вторым параметром. Но здесь всё ясно: каждый из плейсхолдеров, передаваемых вторым параметром, заведомо присутствует в чанке. Поэтому, быстрее будет выполнить str_replace для массива всех этих плейсхолдеров. Что касается $modx->placeholders, то в большинстве чанков они либо будут отсутствовать, либо будет присутствовать только малая часть из них. Поэтому, обработку плейсхолдеров $modx->placeholders быстрее выполнить «по факту» (точечно).

        Можно попробовать сделать двойную обработку:
        // обработка всех переданных плейсхолдеров с условиями
        $html = $modx->pdoTools->getChunk($chunkName, $placeholders, false);
        // подстановка из modX::placeholders
        $html = $modx->pdoTools->fastProcess($html);

        А вот здесь идея не ясна. В первом комментарии идёт речь об обработке плейсхолдеров с условиями. О каких условиях речь? Здесь первый вызов getChunk так и так обработает все плейсхолдеры, включая $modx->placeholders (путём вызова стандартного парсера $modx). И вызов fastProcess уже будет не нужен (отработает «вхолостую»).

        ===================================================================================
        Сабжевая задача выглядит следующим образом:
        а) плейсхолдеры, передаваемые 2-параметром, должны быть обработаны как есть (через массив «плейсхолдеры-значения»), т.к. все они присутствуют в чанке
        б) стандартные плейсхолдеры $modx->placeholders обрабатываются «точечно», т.к. в чанке присутствует только малая часть из них (либо отсутствуют вообще)
        в) если после обработки в чанке остаются какие-либо теги modx, управление передаётся стандартному парсеру $modx

        Сейчас (без переделки кода) возможно реализовать только такие комбинации:
        — либо (а + в)
        — либо (а + б) // fastMode

        ====================================================================================
        Один из вариантов — методу getChunk вместо параметра fastMode передавать 2 параметра:
        — modxPlaceholders — обрабатывать ли $modx->placeholders (обработка выполняется точечно)
        — modxParser — передавать ли обработку стандартному парсеру modx, если остаются теги

        А алгоритм будет таким:
        1. Выполняется обработка quick placeholders, standard placeholders, lexicon placeholders (как сейчас)
        2. Если остаются теги и [modxPaceholders = true], выполняется «точечная» обработка $modx->placeholders
        3. Если остаются теги и [modxParser = true], вызывается стандартный парсер modx

        Такой вариант является более гибким и более быстрым (для случаев, когда чанк содержит стандартные плейсхолдеры modx), а режим fastMode будет равносилен набору параметров [modxPlaceholders = true], [modxParser = false].

        ==============================================================================
        Другой вариант: оставляем параметр fastMode, но при этом «точечная» обработка $modx->placeholders выполняется всегда (если остаются теги modx). При [fastMode = true] обработка стандартному парсеру не передаётся никогда, при [fastMode = false] и при наличии тегов modx обработка передаётся стандартному парсеру.
        В данном варианте параметр fastMode целесообразно будет переименовать, например, в useModxParser.

        Но я за параметры modxPlaceholders и modxParser — это более гибкий вариант.
          Василий Наумкин
          11 декабря 2013, 12:42
          0
          А вот здесь идея не ясна.… Здесь первый вызов getChunk так и так обработает все плейсхолдеры, включая $modx->placeholders
          Не обработает. Эти плейсхолдеры останутся и будут процесситься уже потом, при выводе страницы.
          Причем, не str_replace, а созданием modTag и вызовом modTag::process(), что будет дольше.

          Все остальное — ты там сам усложняй наздоровье, у меня на это времени нет.
          Cyrax_02
          11 декабря 2013, 12:34
          0
          пункт
          2. Если остаются теги и [modxPaceholders = true], выполняется «точечная» обработка $modx->placeholders
          читать так:
          2. Если остаются теги '[[+', '[[!+' и [modxPaceholders = true], выполняется «точечная» обработка $modx->placeholders
      Cyrax_02
      11 декабря 2013, 14:31
      0
      Учитывая, что время работы парсера в сабжевых тестах не учитывается, получаем:
      1)
      $modx->pdoTools->getChunk($chunkName, array_merge($placeholders, $modx->placeholders), false);
      // время: X сек (чанк обрабатывается полностью)
      2)
      $modx->pdoTools->getChunk($chunkName, $placeholders, false);
      // время: 0.5X сек + время обработки $modx->placeholders парсером modx (чанк обрабатывается полностью)
      3)
      $modx->pdoTools->getChunk($chunkName, $placeholders, true);
      // время: 0.2X сек (вложенные чанки и прочие теги не обрабатываются)
      4)
      $html = $modx->pdoTools->getChunk($chunkName, $placeholders, false);
      $html = $modx->pdoTools->fastProcess($html);
      // время: 0,5X (чанк обрабатывается полностью)

      Интерес здесь представляют варианты 1,2,4 (чанк обрабатывается полностью). Вариант 4 по скорости лидирует.
        Cyrax_02
        11 декабря 2013, 14:42
        0
        5)
        $modx->getChunk($chunkName, $placeholders);
        // время: 1.3Х-1.6X сек (чанк обрабатывается полностью)
        Cyrax_02
        11 декабря 2013, 15:41
        0
        Не обработает. Эти плейсхолдеры останутся и будут процесситься уже потом, при выводе страницы.
        Причем, не str_replace, а созданием modTag и вызовом modTag::process(), что будет дольше.

        Проверил — не остаются:
        $html = $modx->pdoTools->getChunk($chunk, $placeholders, false);
        func_dumper($html, true);   // все глобальные плейсхолдеры из $modx->placeholders уже подставлены (в $placeholders их нет)
        $html = $modx->pdoTools->fastProcess($html);

        И pdoTools::fastProcess() отрабатывает уже впустую.

        Вот последний кусок метода getChunk:
        if (strpos($content, '[[') !== false) {
            return $fastMode
                ? $this->fastProcess($content, $properties)
                : $chunk['object']->process($properties, $content);   // вызывается парсер modx, который обрабатывает все оставшиеся теги, в т.ч. $modx->placeholders
        }
          Василий Наумкин
          11 декабря 2013, 16:16
          0
          Значит, я не прав. В любом случае, там обработка через modPlaceholderTag::getContent(), а не через str_replace.

          Так какой из этого всего следует вывод? Что метод pdoTools::getChunk() c fastMode быстрее, но не всё обрабатывает, а без него медленнее?
          Cyrax_02
          11 декабря 2013, 16:23
          0
          Так какой из этого всего следует вывод? Что метод pdoTools::getChunk() c fastMode быстрее, но не всё обрабатывает, а без него медленнее?

          Да, fastMode обрабатывает $modx->placeholders быстрее, но вырезает все прочие теги.

          Получается, что вот эти действия:
          а) плейсхолдеры, передаваемые 2-м параметром, обрабатываются как есть (через массив «плейсхолдеры-значения»);
          б) стандартные плейсхолдеры $modx->placeholders обрабатываются «точечно», т.к. в большинстве чанков присутствует только малая часть из них (либо отсутствуют вообще);
          в) если после обработки в чанке остаются какие-либо теги modx, управление передаётся стандартному парсеру $modx
          на базе имеющихся методов pdoTools никак не реализовать (без коррекции кода)?

          Если нет, состряпаю что-нибудь сам.
            Василий Наумкин
            11 декабря 2013, 16:58
            1
            0
            Думаю, можно добавить обработку modX::placeholders в getChunk. Там уже есть работа с % и ~, пусть будет и ++.

            Состряпал тест:
            $pdo = $modx->getService('pdoFetch');
            $time = microtime(true);
            for ($i = 1; $i <= 1000; $i++) {
            	$res = $pdo->getChunk('@INLINE [[++site_name]]', array(), false);
            }
            echo microtime(true) - $time;

            Со старой передачей в парсер выходит 0.25 сек, с новой — 0.026. Надеюсь, глюков это не прибавит.
              Василий Наумкин
              11 декабря 2013, 19:10
              0
              Попробуй вот эту версию класса, в ней добавлена обработка ++ и *, ну и переписан метод fastProcess().

              Если нормально будет у тебя работать (у себя я уже проверил), то выпущу бету версию.
                Cyrax_02
                11 декабря 2013, 22:06
                0
                Проверил. Всё, что реализовано, — работает нормально (++, *, ~, + передаваемые, + из $modx->placeholders).
                [[% ]] — не проверял.

                В режиме fastMode не работает следующее:
                а) вызовы чанков
                б) теги, содержащие вложенные теги (насколько я понимаю, вложенные теги подставляются, но затем внешний тег вырезается)
                в) ссылки с параметрами, например:
                [[~190? &p1=`111` &p2=`222`]]
                  Василий Наумкин
                  11 декабря 2013, 22:14
                  0
                  Так и должно быть.

                  fastMode на то и fast, что вырезает все лишнее. Для него нужно подготовить чанк, убрать все условия и вложенные вызовы. Например в комментариях к тикетам его просто необходимо использовать, иначе тормоза.

                  Лично я использую его часто, но по умолчанию он отключен.
                    Cyrax_02
                    11 декабря 2013, 22:36
                    0
                    Стоп. Подстановка системных плейсхолдеров из $modx->placeholders не работает.
                    Ставим в чанке, например, [[+modx.user.id]], указываем fastMode, делаем print_r — в результате вызов [[+modx.user.id]] остаётся. Если отменить fastMode — значение подставляется нормально (парсер modx).
                      Cyrax_02
                      11 декабря 2013, 22:48
                      0
                      в строках 347 и 349 нужно плюсик убрать:
                      case '+':
                          if (isset($this->modx->placeholders['+'.$value])) {
                              $src[] = $v[0];
                              $dst[] = $this->modx->placeholders['+'.$value];
                              $processed = true;
                          }
                          break;
                      Cyrax_02
                      11 декабря 2013, 23:01
                      0
                      ++ тоже не работает. Только подстановка системных настроек вроде и не реализована в коде.

                      P.S. * и ~ (без параметров) — работают. Точно.
                  Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                  18