1<?php
2
3/*
4 * This file is part of the Assetic package, an OpenSky project.
5 *
6 * (c) 2010-2014 OpenSky Project Inc
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Assetic\Extension\Twig;
13
14use Assetic\Asset\AssetInterface;
15
16class AsseticNode extends \Twig_Node
17{
18    /**
19     * Constructor.
20     *
21     * Available attributes:
22     *
23     *  * debug:    The debug mode
24     *  * combine:  Whether to combine assets
25     *  * var_name: The name of the variable to expose to the body node
26     *
27     * @param AssetInterface $asset      The asset
28     * @param \Twig_Node     $body       The body node
29     * @param array          $inputs     An array of input strings
30     * @param array          $filters    An array of filter strings
31     * @param string         $name       The name of the asset
32     * @param array          $attributes An array of attributes
33     * @param integer        $lineno     The line number
34     * @param string         $tag        The tag name
35     */
36    public function __construct(AssetInterface $asset, \Twig_Node $body, array $inputs, array $filters, $name, array $attributes = array(), $lineno = 0, $tag = null)
37    {
38        $nodes = array('body' => $body);
39
40        $attributes = array_replace(
41            array('debug' => null, 'combine' => null, 'var_name' => 'asset_url'),
42            $attributes,
43            array('asset' => $asset, 'inputs' => $inputs, 'filters' => $filters, 'name' => $name)
44        );
45
46        parent::__construct($nodes, $attributes, $lineno, $tag);
47    }
48
49    public function compile(\Twig_Compiler $compiler)
50    {
51        $compiler->addDebugInfo($this);
52
53        $combine = $this->getAttribute('combine');
54        $debug = $this->getAttribute('debug');
55
56        if (null === $combine && null !== $debug) {
57            $combine = !$debug;
58        }
59
60        if (null === $combine) {
61            $compiler
62                ->write("if (isset(\$context['assetic']['debug']) && \$context['assetic']['debug']) {\n")
63                ->indent()
64            ;
65
66            $this->compileDebug($compiler);
67
68            $compiler
69                ->outdent()
70                ->write("} else {\n")
71                ->indent()
72            ;
73
74            $this->compileAsset($compiler, $this->getAttribute('asset'), $this->getAttribute('name'));
75
76            $compiler
77                ->outdent()
78                ->write("}\n")
79            ;
80        } elseif ($combine) {
81            $this->compileAsset($compiler, $this->getAttribute('asset'), $this->getAttribute('name'));
82        } else {
83            $this->compileDebug($compiler);
84        }
85
86        $compiler
87            ->write('unset($context[')
88            ->repr($this->getAttribute('var_name'))
89            ->raw("]);\n")
90        ;
91    }
92
93    protected function compileDebug(\Twig_Compiler $compiler)
94    {
95        $i = 0;
96        foreach ($this->getAttribute('asset') as $leaf) {
97            $leafName = $this->getAttribute('name').'_'.$i++;
98            $this->compileAsset($compiler, $leaf, $leafName);
99        }
100    }
101
102    protected function compileAsset(\Twig_Compiler $compiler, AssetInterface $asset, $name)
103    {
104        if ($vars = $asset->getVars()) {
105            $compiler->write("// check variable conditions\n");
106
107            foreach ($vars as $var) {
108                $compiler
109                    ->write("if (!isset(\$context['assetic']['vars']['$var'])) {\n")
110                    ->indent()
111                    ->write("throw new \RuntimeException(sprintf('The asset \"".$name."\" expected variable \"".$var."\" to be set, but got only these vars: %s. Did you set-up a value supplier?', isset(\$context['assetic']['vars']) && \$context['assetic']['vars'] ? implode(', ', \$context['assetic']['vars']) : '# none #'));\n")
112                    ->outdent()
113                    ->write("}\n")
114                ;
115            }
116
117            $compiler->raw("\n");
118        }
119
120        $compiler
121            ->write("// asset \"$name\"\n")
122            ->write('$context[')
123            ->repr($this->getAttribute('var_name'))
124            ->raw('] = ')
125        ;
126
127        $this->compileAssetUrl($compiler, $asset, $name);
128
129        $compiler
130            ->raw(";\n")
131            ->subcompile($this->getNode('body'))
132        ;
133    }
134
135    protected function compileAssetUrl(\Twig_Compiler $compiler, AssetInterface $asset, $name)
136    {
137        if (!$vars = $asset->getVars()) {
138            $compiler->repr($asset->getTargetPath());
139
140            return;
141        }
142
143        $compiler
144            ->raw("strtr(")
145            ->string($asset->getTargetPath())
146            ->raw(", array(");
147
148        $first = true;
149        foreach ($vars as $var) {
150            if (!$first) {
151                $compiler->raw(", ");
152            }
153            $first = false;
154
155            $compiler
156                ->string("{".$var."}")
157                ->raw(" => \$context['assetic']['vars']['$var']")
158            ;
159        }
160
161        $compiler
162            ->raw("))")
163        ;
164    }
165}
166