From 4f5b44bd3bd490309eb2ba7b44df4769816ba729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sat, 3 Aug 2013 19:26:54 +0200 Subject: twig implementation --- .../Symfony/Bridge/Twig/NodeVisitor/Scope.php | 135 ++++++++++++++++++++ .../TranslationDefaultDomainNodeVisitor.php | 106 ++++++++++++++++ .../Twig/NodeVisitor/TranslationNodeVisitor.php | 137 +++++++++++++++++++++ 3 files changed, 378 insertions(+) create mode 100644 vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php create mode 100644 vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php create mode 100644 vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php (limited to 'vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor') diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php new file mode 100644 index 00000000..ce27b6a6 --- /dev/null +++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/Scope.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\NodeVisitor; + +/** + * @author Jean-François Simon + */ +class Scope +{ + /** + * @var Scope|null + */ + private $parent; + + /** + * @var Scope[] + */ + private $children; + + /** + * @var array + */ + private $data; + + /** + * @var boolean + */ + private $left; + + /** + * @param Scope $parent + */ + public function __construct(Scope $parent = null) + { + $this->parent = $parent; + $this->left = false; + $this->data = array(); + } + + /** + * Opens a new child scope. + * + * @return Scope + */ + public function enter() + { + $child = new self($this); + $this->children[] = $child; + + return $child; + } + + /** + * Closes current scope and returns parent one. + * + * @return Scope|null + */ + public function leave() + { + $this->left = true; + + return $this->parent; + } + + /** + * Stores data into current scope. + * + * @param string $key + * @param mixed $value + * + * @throws \LogicException + * + * @return Scope Current scope + */ + public function set($key, $value) + { + if ($this->left) { + throw new \LogicException('Left scope is not mutable.'); + } + + $this->data[$key] = $value; + + return $this; + } + + /** + * Tests if a data is visible from current scope. + * + * @param string $key + * + * @return boolean + */ + public function has($key) + { + if (array_key_exists($key, $this->data)) { + return true; + } + + if (null === $this->parent) { + return false; + } + + return $this->parent->has($key); + } + + /** + * Returns data visible from current scope. + * + * @param string $key + * @param mixed $default + * + * @return mixed + */ + public function get($key, $default = null) + { + if (array_key_exists($key, $this->data)) { + return $this->data[$key]; + } + + if (null === $this->parent) { + return $default; + } + + return $this->parent->get($key, $default); + } +} diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php new file mode 100644 index 00000000..8e7e7f48 --- /dev/null +++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\NodeVisitor; + +use Symfony\Bridge\Twig\Node\TransNode; +use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; + +/** + * TranslationDefaultDomainNodeVisitor. + * + * @author Fabien Potencier + */ +class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface +{ + /** + * @var Scope + */ + private $scope; + + /** + * Constructor. + */ + public function __construct() + { + $this->scope = new Scope(); + } + + /** + * {@inheritdoc} + */ + public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { + $this->scope = $this->scope->enter(); + } + + if ($node instanceof TransDefaultDomainNode) { + if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) { + $this->scope->set('domain', $node->getNode('expr')); + + return $node; + } else { + $var = $env->getParser()->getVarName(); + $name = new \Twig_Node_Expression_AssignName($var, $node->getLine()); + $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getLine())); + + return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine()); + } + } + + if (!$this->scope->has('domain')) { + return $node; + } + + if ($node instanceof \Twig_Node_Expression_Filter && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) { + $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2; + $arguments = $node->getNode('arguments'); + if (!$arguments->hasNode($ind)) { + if (!$arguments->hasNode($ind - 1)) { + $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine())); + } + + $arguments->setNode($ind, $this->scope->get('domain')); + } + } elseif ($node instanceof TransNode) { + if (null === $node->getNode('domain')) { + $node->setNode('domain', $this->scope->get('domain')); + } + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + if ($node instanceof TransDefaultDomainNode) { + return false; + } + + if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { + $this->scope = $this->scope->leave(); + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return -10; + } +} diff --git a/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php new file mode 100644 index 00000000..592c2506 --- /dev/null +++ b/vendor/symfony/twig-bridge/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\NodeVisitor; + +use Symfony\Bridge\Twig\Node\TransNode; + +/** + * TranslationNodeVisitor extracts translation messages. + * + * @author Fabien Potencier + */ +class TranslationNodeVisitor implements \Twig_NodeVisitorInterface +{ + const UNDEFINED_DOMAIN = '_undefined'; + + private $enabled = false; + private $messages = array(); + + public function enable() + { + $this->enabled = true; + $this->messages = array(); + } + + public function disable() + { + $this->enabled = false; + $this->messages = array(); + } + + public function getMessages() + { + return $this->messages; + } + + /** + * {@inheritdoc} + */ + public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + if (!$this->enabled) { + return $node; + } + + if ( + $node instanceof \Twig_Node_Expression_Filter && + 'trans' === $node->getNode('filter')->getAttribute('value') && + $node->getNode('node') instanceof \Twig_Node_Expression_Constant + ) { + // extract constant nodes with a trans filter + $this->messages[] = array( + $node->getNode('node')->getAttribute('value'), + $this->getReadDomainFromArguments($node->getNode('arguments'), 1), + ); + } elseif ( + $node instanceof \Twig_Node_Expression_Filter && + 'transchoice' === $node->getNode('filter')->getAttribute('value') && + $node->getNode('node') instanceof \Twig_Node_Expression_Constant + ) { + // extract constant nodes with a trans filter + $this->messages[] = array( + $node->getNode('node')->getAttribute('value'), + $this->getReadDomainFromArguments($node->getNode('arguments'), 2), + ); + } elseif ($node instanceof TransNode) { + // extract trans nodes + $this->messages[] = array( + $node->getNode('body')->getAttribute('data'), + $this->getReadDomainFromNode($node->getNode('domain')), + ); + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + return $node; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 0; + } + + /** + * @param \Twig_Node $arguments + * @param int $index + * + * @return string|null + */ + private function getReadDomainFromArguments(\Twig_Node $arguments, $index) + { + if ($arguments->hasNode('domain')) { + $argument = $arguments->getNode('domain'); + } elseif ($arguments->hasNode($index)) { + $argument = $arguments->getNode($index); + } else { + return null; + } + + return $this->getReadDomainFromNode($argument); + } + + /** + * @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; + } +} -- cgit v1.2.3