0

我正在编写一个 (Symfony2) SmartyBundle扩展来支持Assetic

为了支持样式表功能,我注册了一个名为的块插件stylesheets

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

当 Symfony/assetic 缓存被创建时,这个插件被正确调用并且一切都按预期工作。

当 Symfony 缓存为空并且 Assetic 加载每个模板文件资源并要求模板引擎检索带有在样式表标签中找到的标记的 PHP 数组时,就会出现问题。调用来检索数组的类是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;
    }

在方法$smarty->fetch()中调用时load()抛出异常:Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException: Circular reference detected in "." ("." > ".").

这是由于 Smarty 模板被解析/编译和stylesheets插件被再次调用造成的。

所以我问 Smarty 是否提供了一个模板解析器来提取块函数标记(不调用样式表插件),这样我就可以提供 Assetic。或者我可能缺少的任何其他解决方案来解决这个问题。

谢谢。

4

1 回答 1

0

在与 Smarty 开发人员 @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

于 2012-03-31T02:28:50.030 回答