0

Asseticをサポートするために(Symfony2)SmartyBundle拡張機能を書いています。

スタイルシート機能をサポートするために、次のブロックプラグインを登録しました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 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

于 2012-03-31T02:28:50.030 に答える