Разбор шаблона Smarty без запуска звонков на пользовательские плагины - PullRequest
0 голосов
/ 21 марта 2012

Я пишу (Symfony2) SmartyBundle расширение для поддержки Assetic .

Для поддержки функции таблиц стилей Я зарегистрировал блочный плагин с именем stylesheets:

{stylesheets
    assets='@SmartyBundle/Resources/public/css/*'
    debug=true}
    <a href="{$asset_url}">{$asset_url}</a>
{/stylesheets}

Этот плагин вызывается правильно, и все работает, как и ожидалось, когда создается Symfony / сборочный кеш.

Проблема возникает, когда кэш Symfony пуст, и Assetic загружает каждый ресурс файла шаблона и просит механизм шаблонов получить массив PHP с токенами, найденными в теге stylesheets. Класс, вызываемый для извлечения массива: SmartyFormulaLoader.

<?php

class SmartyFormulaLoader implements \Assetic\Factory\Loader\FormulaLoaderInterface
{   
    public function load(ResourceInterface $resource)
    {
        // raw template content
        $content = $resource->getContent();

        // a FileLoaderImportCircularReferenceException is throw here
        $smartyParsed = $this->smarty->fetch('string: '.$content);

        // build an array with tokens extracted from the block function
        $formulae = $this->extractStylesheetsTokens($smartyParsed);

        return $formulae;
    }

Когда в методе load() вызывается $smarty->fetch(), генерируется исключение: Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException: Circular reference detected in "." ("." > ".").

Это вызвано тем, что шаблон Smarty анализируется / компилируется и снова вызывается плагин stylesheets.

Поэтому я спрашиваю, предоставляет ли Smarty синтаксический анализатор шаблонов, который извлекает токены блочной функции (без вызова плагина таблиц стилей), чтобы я мог кормить Assetic. Или любое другое решение, которое я могу упустить, чтобы решить эту проблему.

Спасибо.

1 Ответ

0 голосов
/ 31 марта 2012

После небольшого разговора с Smarty dev @rodneyrehm мы пришли к выводу, что:

  1. Следует проанализировать исходный шаблон шаблона вместо компиляции шаблона и его синтаксического анализа
  2. Следует написать мойсобственный синтаксический анализатор (вместо использования некоторого внутреннего помощника Smarty)

Итак, для этого конкретного случая мы придумали следующую реализацию:

<?php

class SmartyFormulaLoader
{
    public function load(ResourceInterface $resource)
    {
        // template source
        $templateSource = $resource->getContent();

        // ask Smarty which delimiters to use
        $ldelim = $smarty->left_delimiter;
        $rdelim = $smarty->right_delimiter;
        $_ldelim = preg_quote($ldelim);
        $_rdelim = preg_quote($rdelim);

        // template block tags to look for
        $tags = implode('|', array('stylesheets', 'javascripts', 'image));

        // match every assetic tag
        if (preg_match_all('#'.$_ldelim.'(?<type>'.$tags.').*?'.$_rdelim.'#s', $templateSource, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                // extract block attributes 
                if (preg_match_all('#(?<key>[a-zA-Z0-9_]+)\s*=\s*(["\']?)(?<value>[^\2]*?)\2(\s|'.$_rdelim.')#s', $match[0], $_matches, PREG_SET_ORDER)) {
                    $t = array(
                        'type'          => $match['type'],
                        'attributes'    => array(),
                    );

                    foreach ($_matches as $_match) {
                        if (empty($_match[2])) {
                            // make eval a little bit safer
                            preg_match('#[^\w|^\.]#', $_match['value'], $evalMatches);
                            $_match['value'] = ($evalMatches) ? null : eval(sprintf('return %s;', $_match['value']));
                        }
                        $t['attributes'][$_match['key']] = $_match['value'];
                    }

                    // call some Assetic methods with the extracted attributes
                    $formulae += $this->buildFormula($match['type'], $t['attributes']);
                }
            }
        }

        return $formulae;
    }
}

Полная реализация доступна здесь: https://github.com/noiselabs/SmartyBundle/blob/master/Assetic/SmartyFormulaLoader.php

...