From 82edad4929cc43900d63e4ce111e642f41eb14b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Wed, 6 Mar 2013 14:23:23 +0100 Subject: [PATCH 1/2] [TwigBridge] added scope management for node visitor --- src/Symfony/Bridge/Twig/NodeVisitor/Scope.php | 91 +++++++++++++++++++ .../TranslationDefaultDomainNodeVisitor.php | 34 +++++-- 2 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Bridge/Twig/NodeVisitor/Scope.php diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php new file mode 100644 index 0000000000000..67faa1e6f29e6 --- /dev/null +++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php @@ -0,0 +1,91 @@ + + */ +class Scope +{ + /** + * @var Scope|null + */ + private $parent; + + /** + * @var Scope[] + */ + private $children; + + /** + * @var array + */ + private $data; + + /** + * @param Scope $parent + */ + public function __construct(Scope $parent = null) + { + $this->parent = $parent; + } + + /** + * Opens a new child scope. + * + * @return Scope + */ + public function open() + { + $child = new self($this); + $this->children[] = $child; + + return $child; + } + + /** + * Closes current scope and returns parent one. + * + * @return Scope|null + */ + public function close() + { + return $this->parent; + } + + /** + * Stores data into current scope. + * + * @param string $key + * @param mixed $value + * + * @return Scope Current scope + */ + public function set($key, $value) + { + $this->data[$key] = $value; + + return $this; + } + + /** + * Returns data visible from current scope. + * + * @param string $key + * @param mixed $default + * + * @return mixed + */ + public function get($key, $default = null) + { + if (isset($this->data[$key])) { + return $this->data[$key]; + } + + if (null === $this->parent) { + return $default; + } + + return $this->parent->get($key, $default); + } +} diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index f6869dee7761e..92257a34f532b 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -21,32 +21,48 @@ */ class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface { - private $domain; + /** + * @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) { + $this->scope = $this->scope->open(); + } + if ($node instanceof \Twig_Node_Module) { - $this->domain = null; + $this->scope->set('domain', null); } if ($node instanceof TransDefaultDomainNode) { if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) { - $this->domain = $node->getNode('expr'); + $this->scope->set('domain', $node->getNode('expr')); return $node; } else { $var = $env->getParser()->getVarName(); $name = new \Twig_Node_Expression_AssignName($var, $node->getLine()); - $this->domain = new \Twig_Node_Expression_Name($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 (null === $this->domain) { + $domain = $this->scope->get('domain'); + if (null === $domain) { return $node; } @@ -58,11 +74,11 @@ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine())); } - $arguments->setNode($ind, $this->domain); + $arguments->setNode($ind, $domain); } } elseif ($node instanceof TransNode) { if (null === $node->getNode('domain')) { - $node->setNode('domain', $this->domain); + $node->setNode('domain', $domain); } } @@ -78,6 +94,10 @@ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) return false; } + if ($node instanceof \Twig_Node_Block) { + $this->scope = $this->scope->close(); + } + return $node; } From 30915d30a2fb8ebda40bfb3842c74096da6a8b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Thu, 7 Mar 2013 15:22:48 +0100 Subject: [PATCH 2/2] [TwigBridge] small fixes --- src/Symfony/Bridge/Twig/NodeVisitor/Scope.php | 40 +++++++++++++++++-- .../TranslationDefaultDomainNodeVisitor.php | 11 +++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php index 67faa1e6f29e6..4993aed90a808 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php @@ -22,12 +22,18 @@ class Scope */ private $data; + /** + * @var boolean + */ + private $left; + /** * @param Scope $parent */ public function __construct(Scope $parent = null) { $this->parent = $parent; + $this->left = false; } /** @@ -35,7 +41,7 @@ public function __construct(Scope $parent = null) * * @return Scope */ - public function open() + public function enter() { $child = new self($this); $this->children[] = $child; @@ -48,8 +54,10 @@ public function open() * * @return Scope|null */ - public function close() + public function leave() { + $this->left = true; + return $this->parent; } @@ -59,15 +67,41 @@ public function close() * @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. * @@ -78,7 +112,7 @@ public function set($key, $value) */ public function get($key, $default = null) { - if (isset($this->data[$key])) { + if (array_key_exists($key, $this->data)) { return $this->data[$key]; } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index 92257a34f532b..f6a764bc6cd00 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -40,7 +40,7 @@ public function __construct() public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { if ($node instanceof \Twig_Node_Block) { - $this->scope = $this->scope->open(); + $this->scope = $this->scope->enter(); } if ($node instanceof \Twig_Node_Module) { @@ -61,8 +61,7 @@ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) } } - $domain = $this->scope->get('domain'); - if (null === $domain) { + if (!$this->scope->has('domain')) { return $node; } @@ -74,11 +73,11 @@ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine())); } - $arguments->setNode($ind, $domain); + $arguments->setNode($ind, $this->scope->get('domain')); } } elseif ($node instanceof TransNode) { if (null === $node->getNode('domain')) { - $node->setNode('domain', $domain); + $node->setNode('domain', $this->scope->get('domain')); } } @@ -95,7 +94,7 @@ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) } if ($node instanceof \Twig_Node_Block) { - $this->scope = $this->scope->close(); + $this->scope = $this->scope->leave(); } return $node;