diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index e7a7155deb..c10dfc577c 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -40,6 +40,7 @@ services: - '@template_context' - '@template.twig.environment' - '@language' + - '@dispatcher' tags: - { name: twig.extension } diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index 982601e41b..9f2bfebb9f 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -28,18 +28,23 @@ class extension extends \Twig\Extension\AbstractExtension /** @var \phpbb\language\language */ protected $language; + /** @var \phpbb\event\dispatcher_interface */ + protected $phpbb_dispatcher; + /** * Constructor * * @param \phpbb\template\context $context * @param \phpbb\template\twig\environment $environment * @param \phpbb\language\language $language + * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher */ - public function __construct(\phpbb\template\context $context, \phpbb\template\twig\environment $environment, $language) + public function __construct(\phpbb\template\context $context, \phpbb\template\twig\environment $environment, $language, \phpbb\event\dispatcher_interface $phpbb_dispatcher) { $this->context = $context; $this->environment = $environment; $this->language = $language; + $this->phpbb_dispatcher = $phpbb_dispatcher; } /** @@ -64,7 +69,7 @@ class extension extends \Twig\Extension\AbstractExtension new \phpbb\template\twig\tokenparser\includeparser, new \phpbb\template\twig\tokenparser\includejs, new \phpbb\template\twig\tokenparser\includecss, - new \phpbb\template\twig\tokenparser\event($this->environment), + new \phpbb\template\twig\tokenparser\event($this->environment, $this->phpbb_dispatcher), ); } diff --git a/phpBB/phpbb/template/twig/node/event.php b/phpBB/phpbb/template/twig/node/event.php index 4eddcbcf38..6b77549b67 100644 --- a/phpBB/phpbb/template/twig/node/event.php +++ b/phpBB/phpbb/template/twig/node/event.php @@ -24,9 +24,13 @@ class event extends \Twig\Node\Node /** @var \phpbb\template\twig\environment */ protected $environment; - public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) + /** @var array */ + protected $template_event_priority_array; + + public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null, $template_event_priority_array = []) { $this->environment = $environment; + $this->template_event_priority_array = $template_event_priority_array; parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } @@ -42,17 +46,26 @@ class event extends \Twig\Node\Node $location = $this->listener_directory . $this->getNode('expr')->getAttribute('name'); + $compiler_steps = []; + foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path) { $ext_namespace = str_replace('/', '_', $ext_namespace); + if (isset($this->template_event_priority_array[$ext_namespace][$location])) + { + $priority_key = $this->template_event_priority_array[$ext_namespace][$location]; + } + + $compiler_calls = []; + if ($this->environment->isDebug()) { // If debug mode is enabled, lets check for new/removed EVENT // templates on page load rather than at compile. This is // slower, but makes developing extensions easier (no need to // purge the cache when a new event template file is added) - $compiler + $compiler_calls[] = fn() => $compiler ->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n") ->indent() ; @@ -60,7 +73,7 @@ class event extends \Twig\Node\Node if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html')) { - $compiler + $compiler_calls[] = fn() => $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 @@ -72,11 +85,39 @@ class event extends \Twig\Node\Node if ($this->environment->isDebug()) { - $compiler + $compiler_calls[] = fn() => $compiler ->outdent() ->write("}\n\n") ; } + + if (!empty($compiler_calls)) + { + if (isset($priority_key)) + { + if (array_key_exists($priority_key, $compiler_steps)) + { + array_splice($compiler_steps, $priority_key, 0, [$compiler_calls]); + } + else + { + $compiler_steps[$priority_key] = $compiler_calls; + } + } + else + { + array_unshift($compiler_steps, $compiler_calls); + } + } + } + + krsort($compiler_steps); + foreach ($compiler_steps as $ext_namespace_steps) + { + foreach ($ext_namespace_steps as $step) + { + $step(); + } } } } diff --git a/phpBB/phpbb/template/twig/tokenparser/event.php b/phpBB/phpbb/template/twig/tokenparser/event.php index 7b9742cc95..3dadc7e3b3 100644 --- a/phpBB/phpbb/template/twig/tokenparser/event.php +++ b/phpBB/phpbb/template/twig/tokenparser/event.php @@ -18,14 +18,38 @@ class event extends \Twig\TokenParser\AbstractTokenParser /** @var \phpbb\template\twig\environment */ protected $environment; + /** @var \phpbb\event\dispatcher_interface */ + protected $phpbb_dispatcher; + + /** @var array */ + protected $template_event_priority_array; + /** * Constructor * * @param \phpbb\template\twig\environment $environment */ - public function __construct(\phpbb\template\twig\environment $environment) + public function __construct(\phpbb\template\twig\environment $environment, \phpbb\event\dispatcher_interface $phpbb_dispatcher = null) { $this->environment = $environment; + $this->phpbb_dispatcher = $phpbb_dispatcher; + + $template_event_priority_array = []; + + /** + * Allow assigning priority to template events + * + * @event core.twig_tokenparser_constructor + * @var array template_event_priority_array Array with template event priority assignments per extension namespace + * @since 3.3.12-RC1 + */ + if ($this->phpbb_dispatcher) + { + $vars = array('template_event_priority_array'); + extract($this->phpbb_dispatcher->trigger_event('core.twig_tokenparser_constructor', compact($vars))); + } + + $this->template_event_priority_array = $template_event_priority_array; } /** @@ -42,7 +66,7 @@ class event extends \Twig\TokenParser\AbstractTokenParser $stream = $this->parser->getStream(); $stream->expect(\Twig\Token::BLOCK_END_TYPE); - return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag()); + return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag(), $this->template_event_priority_array); } /**