/** * Called before child nodes are visited. * * @param Twig_Node $node The node to visit * @param Twig_Environment $env The Twig environment instance * * @return Twig_Node The modified node */ public function enterNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Module) { $this->inAModule = true; $this->tags = array(); $this->filters = array(); $this->functions = array(); return $node; } elseif ($this->inAModule) { // look for tags if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { $this->tags[$node->getNodeTag()] = $node; } // look for filters if ($node instanceof Twig_Node_Expression_Filter && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; } // look for functions if ($node instanceof Twig_Node_Expression_Function && !isset($this->functions[$node->getAttribute('name')])) { $this->functions[$node->getAttribute('name')] = $node; } // wrap print to check __toString() calls if ($node instanceof Twig_Node_Print) { return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag()); } } return $node; }
/** * Loads assets from the supplied node. * * @param \Twig_Node $node * * @return array An array of asset formulae indexed by name */ private function loadNode(\Twig_Node $node) { $formulae = array(); if ($node instanceof AsseticNode) { $formulae[$node->getAttribute('name')] = array($node->getAttribute('inputs'), $node->getAttribute('filters'), array('output' => $node->getAttribute('asset')->getTargetPath(), 'name' => $node->getAttribute('name'), 'debug' => $node->getAttribute('debug'), 'combine' => $node->getAttribute('combine'), 'vars' => $node->getAttribute('vars'))); } elseif ($node instanceof \Twig_Node_Expression_Function) { $name = version_compare(\Twig_Environment::VERSION, '1.2.0-DEV', '<') ? $node->getNode('name')->getAttribute('name') : $node->getAttribute('name'); if ($this->twig->getFunction($name) instanceof AsseticFilterFunction) { $arguments = array(); foreach ($node->getNode('arguments') as $argument) { $arguments[] = eval('return ' . $this->twig->compile($argument) . ';'); } $invoker = $this->twig->getExtension('assetic')->getFilterInvoker($name); $inputs = isset($arguments[0]) ? (array) $arguments[0] : array(); $filters = $invoker->getFilters(); $options = array_replace($invoker->getOptions(), isset($arguments[1]) ? $arguments[1] : array()); if (!isset($options['name'])) { $options['name'] = $invoker->getFactory()->generateAssetName($inputs, $filters, $options); } $formulae[$options['name']] = array($inputs, $filters, $options); } } foreach ($node as $child) { if ($child instanceof \Twig_Node) { $formulae += $this->loadNode($child); } } if ($node->hasAttribute('embedded_templates')) { foreach ($node->getAttribute('embedded_templates') as $child) { $formulae += $this->loadNode($child); } } return $formulae; }
/** * Loads assets from the supplied node. * * @param \Twig_Node $node * * @return array An array of asset formulae indexed by name */ private function loadNode(\Twig_Node $node) { $formulae = array(); if ($node instanceof AsseticNode) { $formulae[$node->getAttribute('name')] = array($node->getAttribute('inputs'), $node->getAttribute('filters'), array('output' => $node->getAttribute('asset')->getTargetPath(), 'name' => $node->getAttribute('name'), 'debug' => $node->getAttribute('debug'), 'combine' => $node->getAttribute('combine'), 'vars' => $node->getAttribute('vars'))); } elseif ($node instanceof \Twig_Node_Expression_Function) { $name = $node->getAttribute('name'); if ($this->twig->getFunction($name) instanceof AsseticFilterFunction) { $arguments = array(); foreach ($node->getNode('arguments') as $argument) { $arguments[] = eval('return ' . $this->twig->compile($argument) . ';'); } $invoker = $this->twig->getExtension('assetic')->getFilterInvoker($name); $inputs = isset($arguments[0]) ? (array) $arguments[0] : array(); $filters = $invoker->getFilters(); $options = array_replace($invoker->getOptions(), isset($arguments[1]) ? $arguments[1] : array()); if (!isset($options['name'])) { $options['name'] = $invoker->getFactory()->generateAssetName($inputs, $filters, $options); } $formulae[$options['name']] = array($inputs, $filters, $options); } } foreach ($node as $child) { if ($child instanceof \Twig_Node) { $formulae += $this->loadNode($child); } } if ($node->hasAttribute('embedded_templates')) { foreach ($node->getAttribute('embedded_templates') as $child) { $formulae += $this->loadNode($child); } } $formulaes = array(); $asseticDebug = $this->app['assetic.debug']; foreach ($formulae as $n => $f) { list($inputs, $filters, $options) = $f; // 當沒有資源或此資源已被解開過的時候 if (count($inputs) > 0 && strlen($n) <= 7 && ($asseticDebug == true || $options['debug'] === true || $options['combine'] === false)) { $path = pathinfo($options['output']); $counter = 1; foreach ($inputs as $input) { $inputPath = pathinfo($input); $_name = $n . '_' . md5($input); $_inputs = array($input); $_filters = $filters; $_options = array('output' => "{$path['dirname']}/{$path['filename']}_{$inputPath['filename']}_{$counter}.{$path['extension']}", 'name' => "{$path['filename']}_{$inputPath['filename']}_{$counter}") + $options; $formulaes[$_name] = array($_inputs, $_filters, $_options); $counter++; } } else { $formulaes[$n] = $f; } } $formulae = $formulaes; return $formulae; }
protected function compileString(\Twig_Node $body) { if ($body instanceof \Twig_Node_Expression_Constant) { $msg = $body->getAttribute('value'); } elseif ($body instanceof \Twig_Node_Text) { $msg = $body->getAttribute('data'); } else { return $body; } return new \Twig_Node_Expression_Constant(trim($msg), $body->getLine()); }
/** * {@inheritdoc} */ public function leaveNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Module) { $varName = $this->getVarName(); $node->setNode('display_start', new Twig_Node(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->getAttribute('filename'), $varName), $node->getNode('display_start')))); $node->setNode('display_end', new Twig_Node(array(new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end')))); } elseif ($node instanceof Twig_Node_Block) { $varName = $this->getVarName(); $node->setNode('body', new Twig_Node_Body(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::BLOCK, $node->getAttribute('name'), $varName), $node->getNode('body'), new Twig_Profiler_Node_LeaveProfile($varName)))); } elseif ($node instanceof Twig_Node_Macro) { $varName = $this->getVarName(); $node->setNode('body', new Twig_Node_Body(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::MACRO, $node->getAttribute('name'), $varName), $node->getNode('body'), new Twig_Profiler_Node_LeaveProfile($varName)))); } return $node; }
public static function process(\Twig_Node $node, Translations $translations, $file) { $fileReference = str_replace(realpath(self::$rootDir . '/../') . '/', "", $file); if ($node instanceof TransNode) { //Process nodes that {% trans %} blocks $body = new \Twig_Node_Expression_Constant($node->getNode('body')->getAttribute('data'), $node->getLine()); $compiledTranslation = eval('return ' . self::$twig->compile($body) . ';'); $translations->insert('', $compiledTranslation)->addReference($fileReference, $node->getLine()); } if ($node instanceof \Twig_Node_Expression_Function) { //Process nodes that are function expressions if ($node->getAttribute('name') == '__') { //Check the function name for __() foreach ($node->getNode('arguments') as $argument) { //Grab the argument $key = eval('return ' . self::$twig->compile($argument) . ';'); $translations->insert('', $key)->addReference($fileReference, $node->getLine()); break; //I only needed the first argument in my implementation } } } //Recursively loop through the AST foreach ($node as $child) { if ($child instanceof \Twig_Node) { self::process($child, $translations, $file); } } }
private function loadNode(Node $node, $resource) { $assets = array(); if ($node instanceof ExpressionFunction) { $name = $node->getAttribute('name'); if ($name === $this->functionName) { $arguments = iterator_to_array($node->getNode('arguments')); if (!is_array($arguments)) { throw new ResourceParsingException('arguments is not an array'); } if (count($arguments) !== 1 && count($arguments) !== 2) { throw new ResourceParsingException(sprintf('Expected exactly one or two arguments passed to function %s in %s at line %s', $this->functionName, $resource, $node->getLine())); } if (!$arguments[0] instanceof ConstantFunction) { throw new ResourceParsingException(sprintf('Argument passed to function %s must be text node to parse without context. File %s, line %s', $this->functionName, $resource, $node->getLine())); } $assets[] = $arguments[0]->getAttribute('value'); return $assets; } } foreach ($node as $child) { if ($child instanceof Node) { $assets = array_merge($assets, $this->loadNode($child, $resource)); } } return $assets; }
/** * {@inheritdoc} */ protected function doEnterNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Module) { if ($env->hasExtension('escaper') && ($defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename')))) { $this->defaultStrategy = $defaultStrategy; } $this->safeVars = array(); } elseif ($node instanceof Twig_Node_AutoEscape) { $this->statusStack[] = $node->getAttribute('value'); } elseif ($node instanceof Twig_Node_Block) { $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); } elseif ($node instanceof Twig_Node_Import) { $this->safeVars[] = $node->getNode('var')->getAttribute('name'); } return $node; }
protected function compileString(\Twig_Node $body, \Twig_Node_Expression_Array $vars, $ignoreStrictCheck = false) { // Extract the message to be translated, or return if it doesn't need translations if ($body instanceof \Twig_Node_Expression_Constant) { $msg = $body->getAttribute('value'); } elseif ($body instanceof \Twig_Node_Text) { $msg = $body->getAttribute('data'); } else { return array($body, $vars); } // Escape variable passed using 'with' // {% safetrans with {...} %}{% endsafetrans %} $vars = $this->escapeWithVariables($vars, $body->getLine()); // Escape variables that needs to be read from $context // {% safetrans %}...{% endsafetrans %} $vars = $this->escapeContextVariables($msg, $vars, $body->getLine()); return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars); }
protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) { if ($node instanceof WhitespaceCollapse || $node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_AutoEscape) { array_pop($this->statusStack); } elseif ($node instanceof \Twig_Node_BlockReference) { $this->blocks[$node->getAttribute('name')] = $this->needCollapsing(); } elseif ($node instanceof \Twig_Node_Text && $this->needCollapsing()) { $text = $node->getAttribute('data'); if ($this->previousNode instanceof \Twig_Node_Text && ctype_space(substr($this->previousNode->getAttribute('data'), -1))) { $text = ltrim($text); } if ($text === '') { return false; } $node->setAttribute('data', preg_replace(array('/\\s{2,}/', '/<\\s/', '/\\s>/'), array(' ', '<', '>'), $text)); } $this->previousNode = $node; return $node; }
/** * Find placeholder nodes recursively. * * @param Twig_Node $node * @param array $placeholders */ protected function getVariables($node, &$placeholders) { if ($node instanceof Curry_Twig_Node_Placeholder) { $placeholders[$node->getAttribute('name')] = true; } foreach ($node->getIterator() as $n) { if ($n instanceof Twig_Node) { $this->getVariables($n, $placeholders); } } }
public function __construct(\Twig_Node $left, \Twig_Node $right, $lineno) { parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno); if ($left instanceof \Twig_Node_Expression_Name) { $this->arguments = [$left->getAttribute('name')]; } elseif ($left instanceof Arguments) { $this->arguments = $left->getArguments(); } else { throw new \InvalidArgumentException('Invalid argument\'s list for lambda.'); } if (count($this->arguments) !== count(array_flip($this->arguments))) { throw new \InvalidArgumentException('Each lambda argument must have unique name.'); } }
protected function compileString(\Twig_Node $body, \Twig_Node_Expression_Array $vars, $ignoreStrictCheck = false) { if ($body instanceof \Twig_Node_Expression_Constant) { $msg = $body->getAttribute('value'); } elseif ($body instanceof \Twig_Node_Text) { $msg = $body->getAttribute('data'); } else { return array($body, $vars); } preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches); foreach ($matches[1] as $var) { $key = new \Twig_Node_Expression_Constant('%' . $var . '%', $body->getLine()); if (!$vars->hasElement($key)) { if ('count' === $var && null !== $this->getNode('count')) { $vars->addElement($this->getNode('count'), $key); } else { $varExpr = new \Twig_Node_Expression_Name($var, $body->getLine()); $varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck); $vars->addElement($varExpr, $key); } } } return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars); }
/** * Compiles a node. * * @param Twig_Node $node The node to compile * @param int $indentation The current indentation * * @return Twig_Compiler The current compiler instance */ public function compile(Twig_Node $node, $indentation = 0) { $this->lastLine = null; $this->source = ''; $this->debugInfo = array(); $this->sourceOffset = 0; // source code starts at 1 (as we then increment it when we encounter new lines) $this->sourceLine = 1; $this->indentation = $indentation; if ($node instanceof Twig_Node_Module) { $this->filename = $node->getAttribute('filename'); } $node->compile($this); return $this; }
/** * Loads assets from the supplied node. * * @return array An array of asset formulae indexed by name */ private function loadNode(\Twig_Node $node) { $assets = array(); if ($node instanceof AsseticNode) { $assets[$node->getAttribute('name')] = array($node->getAttribute('inputs'), $node->getAttribute('filters'), array('output' => $node->getAttribute('output'), 'name' => $node->getAttribute('name'), 'debug' => $node->getAttribute('debug'))); } foreach ($node as $child) { if ($child instanceof \Twig_Node) { $assets += $this->loadNode($child); } } return $assets; }
/** * {@inheritdoc} */ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) { if ($node instanceof \Twig_Node_Module) { $this->filename = $node->getAttribute('filename'); } if ($this->shouldProcess()) { if ($this->isBufferizingNode($node)) { $this->shouldBufferize = true; } if ($node instanceof \Twig_Node_Module) { $this->blocks = $node->getNode('blocks')->getIterator()->getArrayCopy(); } if ($node instanceof \Twig_Node_Body) { $this->currentScope = null; } elseif ($node instanceof \Twig_Node_Block) { $this->currentScope = $node->getAttribute('name'); } } return $node; }
/** * Extracts formulae from filter function nodes. * * @return array|null The formula */ private function checkNode(\Twig_Node $node, \Twig_Environment $env, &$name = null) { if ($node instanceof \Twig_Node_Expression_Function) { $name = $node->getAttribute('name'); if ($env->getFunction($name) instanceof AsseticFilterFunction) { $arguments = array(); foreach ($node->getNode('arguments') as $argument) { $arguments[] = eval('return ' . $env->compile($argument) . ';'); } $invoker = $env->getExtension('assetic')->getFilterInvoker($name); $factory = $invoker->getFactory(); $inputs = isset($arguments[0]) ? (array) $arguments[0] : array(); $filters = $invoker->getFilters(); $options = array_replace($invoker->getOptions(), isset($arguments[1]) ? $arguments[1] : array()); if (!isset($options['name'])) { $options['name'] = $factory->generateAssetName($inputs, $filters); } return array($inputs, $filters, $options); } } }
/** * Loads assets from the supplied node. * * @return array An array of asset formulae indexed by name */ private function loadNode(\Twig_Node $node) { $assets = array(); if ($node instanceof Node) { $assets[$node->getAttribute('asset_name')] = array( $node->getAttribute('source_urls'), $node->getAttribute('filter_names'), array( 'output' => $node->getAttribute('target_url'), 'name' => $node->getAttribute('asset_name'), 'debug' => $node->getAttribute('debug'), ), ); } foreach ($node as $child) { if ($child instanceof \Twig_Node) { $assets += $this->loadNode($child); } } return $assets; }
/** * @param \Twig_Node $node * @param $name * @return mixed|null */ public function getAttribute(\Twig_Node $node, $name) { return $node->hasAttribute($name) ? $node->getAttribute($name) : null; }
private function filterBodyNodes(Twig_Node $node) { // check that the body does not contain non-empty output nodes if ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data')) || !$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) { if (false !== strpos((string) $node, chr(0xef) . chr(0xbb) . chr(0xbf))) { throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getLine(), $this->getFilename()); } throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getLine(), $this->getFilename()); } // bypass "set" nodes as they "capture" the output if ($node instanceof Twig_Node_Set) { return $node; } if ($node instanceof Twig_NodeOutputInterface) { return; } foreach ($node as $k => $n) { if (null !== $n && null === $this->filterBodyNodes($n)) { $node->removeNode($k); } } return $node; }
protected function dumpAssets(Node $node, AssetCollectionInterface $asset, $tagName, $assetPath, array $combination = array()) { $inputs = $this->collectInputs($asset->all(), $combination, $node->getAttribute('inputs')); $this->assetFileDumper->dump($assetPath, $inputs); $aliasedAssetPath = $this->aliasPrefixer->prefixWithAlias($assetPath); $arguments = array(str_replace('\\/', '/', json_encode($aliasedAssetPath))); if ($tagName === 'stylesheets') { $arguments[] = json_encode('css'); } return $this->twigFunctionName . '(' . implode(', ', $arguments) . ')'; }
/** * @param \Twig_Node $node * * @return string|null */ private function getReadDomainFromNode(\Twig_Node $node = null) { if (null === $node) { return null; } if ($node instanceof \Twig_Node_Expression_Constant) { return $node->getAttribute('value'); } return self::UNDEFINED_DOMAIN; }
/** * Extract a message from a \Twig_Node_Print * Return null if not a constant message * * @param \Twig_Node $node */ private function _extractMessage(\Twig_Node $node) { if($node->hasNode('node')) { return $this->_extractMessage($node->getNode ('node')); } if($node instanceof \Twig_Node_Expression_Constant) { return $node->getAttribute('value'); } return null; }
/** * If the current Twig Node has embedded templates, we want to travese these templates * in the same manner as we do the main twig template to ensure all translations are * caught. * * @param \Twig_Node $node */ private function traverseEmbeddedTemplates(\Twig_Node $node) { $templates = $node->getAttribute('embedded_templates'); foreach ($templates as $template) { $this->traverser->traverse($template); if ($template->hasAttribute('embedded_templates')) { $this->traverseEmbeddedTemplates($template); } } }