source: sandbox/newExpressoMail/newExpressoMail/Assetic/Factory/Loader/BasePhpFormulaLoader.php @ 7265

Revision 7265, 4.8 KB checked in by gustavo, 12 years ago (diff)

Ticket #0000 - Criado novo modulo para o desenvolvimento do novo ExpressoMail?

  • Property svn:executable set to *
Line 
1<?php
2
3/*
4 * This file is part of the Assetic package, an OpenSky project.
5 *
6 * (c) 2010-2012 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\Factory\Loader;
13
14use Assetic\Factory\AssetFactory;
15use Assetic\Factory\Resource\ResourceInterface;
16
17/**
18 * Loads asset formulae from PHP files.
19 *
20 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
21 */
22abstract class BasePhpFormulaLoader implements FormulaLoaderInterface
23{
24    protected $factory;
25    protected $prototypes;
26
27    public function __construct(AssetFactory $factory)
28    {
29        $this->factory = $factory;
30        $this->prototypes = array();
31
32        foreach ($this->registerPrototypes() as $prototype => $options) {
33            $this->addPrototype($prototype, $options);
34        }
35    }
36
37    public function addPrototype($prototype, array $options = array())
38    {
39        $tokens = token_get_all('<?php '.$prototype);
40        array_shift($tokens);
41
42        $this->prototypes[$prototype] = array($tokens, $options);
43    }
44
45    public function load(ResourceInterface $resource)
46    {
47        if (!$nbProtos = count($this->prototypes)) {
48            throw new \LogicException('There are no prototypes registered.');
49        }
50
51        $buffers = array_fill(0, $nbProtos, '');
52        $bufferLevels = array_fill(0, $nbProtos, 0);
53        $buffersInWildcard = array();
54
55        $tokens = token_get_all($resource->getContent());
56        $calls = array();
57
58        while ($token = array_shift($tokens)) {
59            $current = self::tokenToString($token);
60            // loop through each prototype (by reference)
61            foreach (array_keys($this->prototypes) as $i) {
62                $prototype =& $this->prototypes[$i][0];
63                $options = $this->prototypes[$i][1];
64                $buffer =& $buffers[$i];
65                $level =& $bufferLevels[$i];
66
67                if (isset($buffersInWildcard[$i])) {
68                    switch ($current) {
69                        case '(': ++$level; break;
70                        case ')': --$level; break;
71                    }
72
73                    $buffer .= $current;
74
75                    if (!$level) {
76                        $calls[] = array($buffer.';', $options);
77                        $buffer = '';
78                        unset($buffersInWildcard[$i]);
79                    }
80                } elseif ($current == self::tokenToString(current($prototype))) {
81                    $buffer .= $current;
82                    if ('*' == self::tokenToString(next($prototype))) {
83                        $buffersInWildcard[$i] = true;
84                        ++$level;
85                    }
86                } else {
87                    reset($prototype);
88                    unset($buffersInWildcard[$i]);
89                    $buffer = '';
90                }
91            }
92        }
93
94        $formulae = array();
95        foreach ($calls as $call) {
96            $formulae += call_user_func_array(array($this, 'processCall'), $call);
97        }
98
99        return $formulae;
100    }
101
102    private function processCall($call, array $protoOptions = array())
103    {
104        $tmp = tempnam(sys_get_temp_dir(), 'assetic');
105        file_put_contents($tmp, implode("\n", array(
106            '<?php',
107            $this->registerSetupCode(),
108            $call,
109            'echo serialize($_call);',
110        )));
111        $args = unserialize(shell_exec('php '.escapeshellarg($tmp)));
112        unlink($tmp);
113
114        $inputs  = isset($args[0]) ? self::argumentToArray($args[0]) : array();
115        $filters = isset($args[1]) ? self::argumentToArray($args[1]) : array();
116        $options = isset($args[2]) ? $args[2] : array();
117
118        if (!isset($options['debug'])) {
119            $options['debug'] = $this->factory->isDebug();
120        }
121
122        if (!is_array($options)) {
123            throw new \RuntimeException('The third argument must be omitted, null or an array.');
124        }
125
126        // apply the prototype options
127        $options += $protoOptions;
128
129        if (!isset($options['name'])) {
130            $options['name'] = $this->factory->generateAssetName($inputs, $filters, $options);
131        }
132
133        return array($options['name'] => array($inputs, $filters, $options));
134    }
135
136    /**
137     * Returns an array of prototypical calls and options.
138     *
139     * @return array Prototypes and options
140     */
141    abstract protected function registerPrototypes();
142
143    /**
144     * Returns setup code for the reflection scriptlet.
145     *
146     * @return string Some PHP setup code
147     */
148    abstract protected function registerSetupCode();
149
150    protected static function tokenToString($token)
151    {
152        return is_array($token) ? $token[1] : $token;
153    }
154
155    protected static function argumentToArray($argument)
156    {
157        return is_array($argument) ? $argument : array_filter(array_map('trim', explode(',', $argument)));
158    }
159}
Note: See TracBrowser for help on using the repository browser.