diff --git a/phpBB/includes/template/twig/environment.php b/phpBB/includes/template/twig/environment.php index b3e1ed9295..4c7f0002ba 100644 --- a/phpBB/includes/template/twig/environment.php +++ b/phpBB/includes/template/twig/environment.php @@ -20,6 +20,9 @@ class phpbb_template_twig_environment extends Twig_Environment /** @var array */ protected $phpbbExtensions; + /** @var array **/ + protected $namespaceLookUpOrder = array('__main__'); + /** * Gets the cache filename for a given template. * @@ -36,16 +39,89 @@ class phpbb_template_twig_environment extends Twig_Environment return $this->getCache() . '/' . preg_replace('#[^a-zA-Z0-9_/]#', '_', $name) . '.php'; } - public function set_phpbb_extensions($extensions) - { - $this->phpbbExtensions = $extensions; - } - + /** + * Get the list of enabled phpBB extensions + * + * @return array + */ public function get_phpbb_extensions() { return $this->phpbbExtensions; } + /** + * Store the list of enabled phpBB extensions + * + * @param array $extensions + * @return Twig_Environment + */ + public function set_phpbb_extensions($extensions) + { + $this->phpbbExtensions = $extensions; + + return $this; + } + + /** + * Get the namespace look up order + * + * @return array + */ + public function getNamespaceLookUpOrder() + { + return $this->namespaceLookUpOrder; + } + + /** + * Set the namespace look up order to load templates from + * + * @param array $namespace + * @return Twig_Environment + */ + public function setNamespaceLookUpOrder($namespace) + { + $this->namespaceLookUpOrder = $namespace; + + return $this; + } + + /** + * Loads a template by name. + * + * @param string $name The template name + * @param integer $index The index if it is an embedded template + * + * @return Twig_TemplateInterface A template instance representing the given template name + */ + public function loadTemplate($name, $index = null) + { + if (strpos($name, '@') === false) + { + foreach ($this->namespaceLookUpOrder as $namespace) + { + try + { + if ($namespace === '__main__') + { + return parent::loadTemplate($name, $index); + } + + return parent::loadTemplate('@' . $namespace . '/' . $name, $index); + } + catch (Twig_Error_Loader $e) + { + } + } + + // We were unable to load any templates + throw $e; + } + else + { + return parent::loadTemplate($name, $index); + } + } + /** * recursive helper to set variables into $context so that Twig can properly fetch them for display * diff --git a/phpBB/includes/template/twig/node/event.php b/phpBB/includes/template/twig/node/event.php index c76c727ba5..cedfa870fa 100644 --- a/phpBB/includes/template/twig/node/event.php +++ b/phpBB/includes/template/twig/node/event.php @@ -37,7 +37,14 @@ class phpbb_template_twig_node_event extends Twig_Node if ($this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html')) { - $compiler->write("\$this->env->loadTemplate('@" . $ext_namespace . "/" . $location . ".html')->display(\$context);\n"); + $compiler + ->write("\$previous_look_up_order = \$this->env->getNamespaceLookUpOrder();\n") + + // We set the namespace lookup order to be this extension first, then the main path + ->write("\$this->env->setNamespaceLookUpOrder(array('" . $ext_namespace . "', '__main__'));\n") + ->write("\$this->env->loadTemplate('@" . $ext_namespace . "/" . $location . ".html')->display(\$context);\n") + ->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n") + ; } } } diff --git a/phpBB/includes/template/twig/node/include.php b/phpBB/includes/template/twig/node/include.php new file mode 100644 index 0000000000..df7a95af44 --- /dev/null +++ b/phpBB/includes/template/twig/node/include.php @@ -0,0 +1,45 @@ +addDebugInfo($this); + + $location = $this->getNode('expr')->getAttribute('value'); + $namespace = false; + + if (strpos($location, '@') === 0) + { + $namespace = substr($location, 1, strpos($location, '/') - 1); + + $compiler + ->write("\$previous_look_up_order = \$this->env->getNamespaceLookUpOrder();\n") + + // We set the namespace lookup order to be this namespace first, then the main path + ->write("\$this->env->setNamespaceLookUpOrder(array('" . $namespace . "', '__main__'));\n") + ; + } + + parent::compile($compiler); + + if ($namespace) + { + $compiler + ->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n") + ; + } + } +} diff --git a/phpBB/includes/template/twig/tokenparser/include.php b/phpBB/includes/template/twig/tokenparser/include.php index d9421095d1..32e1cd331d 100644 --- a/phpBB/includes/template/twig/tokenparser/include.php +++ b/phpBB/includes/template/twig/tokenparser/include.php @@ -21,6 +21,22 @@ */ class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include { + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + return new phpbb_template_twig_node_include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + /** * Gets the tag name associated with this token parser. *