diff -r 000000000000 -r 7f95f8617b0b vendor/assetic/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/assetic/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php Sat Sep 24 15:40:41 2011 +0200 @@ -0,0 +1,159 @@ + + */ +abstract class BasePhpFormulaLoader implements FormulaLoaderInterface +{ + protected $factory; + protected $prototypes; + + public function __construct(AssetFactory $factory) + { + $this->factory = $factory; + $this->prototypes = array(); + + foreach ($this->registerPrototypes() as $prototype => $options) { + $this->addPrototype($prototype, $options); + } + } + + public function addPrototype($prototype, array $options = array()) + { + $tokens = token_get_all('prototypes[$prototype] = array($tokens, $options); + } + + public function load(ResourceInterface $resource) + { + if (!$nbProtos = count($this->prototypes)) { + throw new \LogicException('There are no prototypes registered.'); + } + + $buffers = array_fill(0, $nbProtos, ''); + $bufferLevels = array_fill(0, $nbProtos, 0); + $buffersInWildcard = array(); + + $tokens = token_get_all($resource->getContent()); + $calls = array(); + + while ($token = array_shift($tokens)) { + $current = self::tokenToString($token); + // loop through each prototype (by reference) + foreach (array_keys($this->prototypes) as $i) { + $prototype =& $this->prototypes[$i][0]; + $options = $this->prototypes[$i][1]; + $buffer =& $buffers[$i]; + $level =& $bufferLevels[$i]; + + if (isset($buffersInWildcard[$i])) { + switch ($current) { + case '(': ++$level; break; + case ')': --$level; break; + } + + $buffer .= $current; + + if (!$level) { + $calls[] = array($buffer.';', $options); + $buffer = ''; + unset($buffersInWildcard[$i]); + } + } elseif ($current == self::tokenToString(current($prototype))) { + $buffer .= $current; + if ('*' == self::tokenToString(next($prototype))) { + $buffersInWildcard[$i] = true; + ++$level; + } + } else { + reset($prototype); + unset($buffersInWildcard[$i]); + $buffer = ''; + } + } + } + + $formulae = array(); + foreach ($calls as $call) { + $formulae += call_user_func_array(array($this, 'processCall'), $call); + } + + return $formulae; + } + + private function processCall($call, array $protoOptions = array()) + { + $tmp = tempnam(sys_get_temp_dir(), 'assetic'); + file_put_contents($tmp, implode("\n", array( + 'registerSetupCode(), + $call, + 'echo serialize($_call);', + ))); + $args = unserialize(shell_exec('php '.escapeshellarg($tmp))); + unlink($tmp); + + $inputs = isset($args[0]) ? self::argumentToArray($args[0]) : array(); + $filters = isset($args[1]) ? self::argumentToArray($args[1]) : array(); + $options = isset($args[2]) ? $args[2] : array(); + + if (!isset($options['debug'])) { + $options['debug'] = $this->factory->isDebug(); + } + + if (!is_array($options)) { + throw new \RuntimeException('The third argument must be omitted, null or an array.'); + } + + // apply the prototype options + $options += $protoOptions; + + if (!isset($options['name'])) { + $options['name'] = $this->factory->generateAssetName($inputs, $filters, $options); + } + + return array($options['name'] => array($inputs, $filters, $options)); + } + + /** + * Returns an array of prototypical calls and options. + * + * @return array Prototypes and options + */ + abstract protected function registerPrototypes(); + + /** + * Returns setup code for the reflection scriptlet. + * + * @return string Some PHP setup code + */ + abstract protected function registerSetupCode(); + + static protected function tokenToString($token) + { + return is_array($token) ? $token[1] : $token; + } + + static protected function argumentToArray($argument) + { + return is_array($argument) ? $argument : array_filter(array_map('trim', explode(',', $argument))); + } +}