Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.23% covered (success)
91.23%
52 / 57
87.50% covered (warning)
87.50%
14 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
environment
91.23% covered (success)
91.23%
52 / 57
87.50% covered (warning)
87.50%
14 / 16
29.57
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 get_phpbb_extensions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 get_phpbb_config
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_phpbb_root_path
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_filesystem
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_web_root_path
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_path_helper
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_assets_bag
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNamespaceLookUpOrder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNamespaceLookUpOrder
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 display
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 display_with_assets
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
4
 inject_assets
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 loadTemplate
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
5.39
 findTemplate
62.50% covered (warning)
62.50%
5 / 8
0.00% covered (danger)
0.00%
0 / 1
6.32
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14namespace phpbb\template\twig;
15
16use phpbb\config\config;
17use phpbb\event\dispatcher_interface;
18use phpbb\extension\manager;
19use phpbb\filesystem\filesystem;
20use phpbb\path_helper;
21use phpbb\template\assets_bag;
22use Twig\Loader\LoaderInterface;
23
24class environment extends \Twig\Environment
25{
26    /** @var config */
27    protected $phpbb_config;
28
29    /** @var filesystem */
30    protected $filesystem;
31
32    /** @var path_helper */
33    protected $phpbb_path_helper;
34
35    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
36    protected $container;
37
38    /** @var manager */
39    protected $extension_manager;
40
41    /** @var dispatcher_interface */
42    protected $phpbb_dispatcher;
43
44    /** @var string */
45    protected $phpbb_root_path;
46
47    /** @var string */
48    protected $web_root_path;
49
50    /** @var array **/
51    protected $namespace_look_up_order = array('__main__');
52
53    /** @var assets_bag */
54    protected $assets_bag;
55
56    /**
57    * Constructor
58    *
59    * @param assets_bag $assets_bag Assets bag
60    * @param config $phpbb_config The phpBB configuration
61    * @param filesystem $filesystem
62    * @param path_helper $path_helper phpBB path helper
63    * @param string $cache_path The path to the cache directory
64    * @param manager|null $extension_manager phpBB extension manager
65    * @param LoaderInterface|null $loader Twig loader interface
66    * @param dispatcher_interface|null    $phpbb_dispatcher    Event dispatcher object
67    * @param array $options Array of options to pass to Twig
68    */
69    public function __construct(assets_bag $assets_bag, config $phpbb_config, filesystem $filesystem, path_helper $path_helper, $cache_path, manager $extension_manager = null, LoaderInterface $loader = null, dispatcher_interface $phpbb_dispatcher = null, $options = array())
70    {
71        $this->phpbb_config = $phpbb_config;
72
73        $this->filesystem = $filesystem;
74        $this->phpbb_path_helper = $path_helper;
75        $this->extension_manager = $extension_manager;
76        $this->phpbb_dispatcher = $phpbb_dispatcher;
77
78        $this->phpbb_root_path = $this->phpbb_path_helper->get_phpbb_root_path();
79
80        $this->assets_bag = $assets_bag;
81
82        $options = array_merge(array(
83            'cache'            => (defined('IN_INSTALL')) ? false : $cache_path,
84            'debug'            => false,
85            'auto_reload'    => (bool) $this->phpbb_config['load_tplcompile'],
86            'autoescape'    => false,
87        ), $options);
88
89        parent::__construct($loader, $options);
90    }
91
92    /**
93    * Get the list of enabled phpBB extensions
94    *
95    * Used in EVENT node
96    *
97    * @return array
98    */
99    public function get_phpbb_extensions()
100    {
101        return ($this->extension_manager) ? $this->extension_manager->all_enabled() : array();
102    }
103
104    /**
105    * Get phpBB config
106    *
107    * @return config
108    */
109    public function get_phpbb_config()
110    {
111        return $this->phpbb_config;
112    }
113
114    /**
115     * Get the phpBB root path
116     *
117     * @return string
118     */
119    public function get_phpbb_root_path()
120    {
121        return $this->phpbb_root_path;
122    }
123
124    /**
125    * Get the filesystem object
126    *
127    * @return filesystem
128    */
129    public function get_filesystem()
130    {
131        return $this->filesystem;
132    }
133
134    /**
135    * Get the web root path
136    *
137    * @return string
138    */
139    public function get_web_root_path()
140    {
141        return $this->web_root_path ?? $this->web_root_path = $this->phpbb_path_helper->get_web_root_path();
142    }
143
144    /**
145    * Get the phpbb path helper object
146    *
147    * @return path_helper
148    */
149    public function get_path_helper()
150    {
151        return $this->phpbb_path_helper;
152    }
153
154    /**
155     * Gets the assets bag
156     *
157     * @return assets_bag
158     */
159    public function get_assets_bag()
160    {
161        return $this->assets_bag;
162    }
163
164    /**
165    * Get the namespace look up order
166    *
167    * @return array
168    */
169    public function getNamespaceLookUpOrder()
170    {
171        return $this->namespace_look_up_order;
172    }
173
174    /**
175    * Set the namespace look up order to load templates from
176    *
177    * @param array $namespace
178    * @return \Twig\Environment
179    */
180    public function setNamespaceLookUpOrder($namespace)
181    {
182        $this->namespace_look_up_order = $namespace;
183
184        return $this;
185    }
186
187    /**
188     * {@inheritdoc}
189     */
190    public function render($name, array $context = []) : string
191    {
192        return $this->display_with_assets($name, $context);
193    }
194
195    /**
196     * {@inheritdoc}
197     */
198    public function display($name, array $context = []) : void
199    {
200        echo $this->display_with_assets($name, $context);
201    }
202
203    /**
204     * Get template with assets
205     */
206    private function display_with_assets($name, array $context = [])
207    {
208        $placeholder_salt = unique_id();
209
210        if (array_key_exists('definition', $context))
211        {
212            $context['definition']->set('SCRIPTS', '__SCRIPTS_' . $placeholder_salt . '__');
213            $context['definition']->set('STYLESHEETS', '__STYLESHEETS_' . $placeholder_salt . '__');
214        }
215
216        /**
217        * Allow changing the template output stream before rendering
218        *
219        * @event core.twig_environment_render_template_before
220        * @var    array    context        Array with template variables
221        * @var    string  name        The template name
222        * @since 3.2.1-RC1
223        */
224        if ($this->phpbb_dispatcher)
225        {
226            $vars = array('context', 'name');
227            extract($this->phpbb_dispatcher->trigger_event('core.twig_environment_render_template_before', compact($vars)));
228        }
229
230        $output = parent::render($name, $context);
231
232        /**
233        * Allow changing the template output stream after rendering
234        *
235        * @event core.twig_environment_render_template_after
236        * @var    array    context        Array with template variables
237        * @var    string  name        The template name
238        * @var    string    output        Rendered template output stream
239        * @since 3.2.1-RC1
240        */
241        if ($this->phpbb_dispatcher)
242        {
243            $vars = array('context', 'name', 'output');
244            extract($this->phpbb_dispatcher->trigger_event('core.twig_environment_render_template_after', compact($vars)));
245        }
246
247        return $this->inject_assets($output, $placeholder_salt);
248    }
249
250    /**
251     * Injects the assets (from INCLUDECSS/JS) in the output.
252     *
253     * @param string $output
254     *
255     * @return string
256     */
257    private function inject_assets($output, $placeholder_salt)
258    {
259        $output = str_replace('__STYLESHEETS_' . $placeholder_salt . '__', $this->assets_bag->get_stylesheets_content(), $output);
260        $output = str_replace('__SCRIPTS_' . $placeholder_salt . '__', $this->assets_bag->get_scripts_content(), $output);
261
262        return $output;
263    }
264
265    /**
266    * Loads a template by name.
267    *
268    * @param string  $cls   The template class associated with the given template name
269    * @param string  $name  The template name
270    * @param integer|null $index The index if it is an embedded template
271    * @return \Twig\Template A template instance representing the given template name
272    * @throws \Twig\Error\LoaderError
273    */
274    public function loadTemplate(string $cls, string $name, int $index = null) : \Twig\Template
275    {
276        if (strpos($name, '@') === false)
277        {
278            foreach ($this->getNamespaceLookUpOrder() as $namespace)
279            {
280                try
281                {
282                    if ($namespace === '__main__')
283                    {
284                        return parent::loadTemplate($cls, $name, $index);
285                    }
286
287                    return parent::loadTemplate($this->getTemplateClass('@' . $namespace . '/' . $name), '@' . $namespace . '/' . $name, $index);
288                }
289                catch (\Twig\Error\LoaderError $e)
290                {
291                }
292            }
293
294            // We were unable to load any templates
295            throw $e;
296        }
297        else
298        {
299            return parent::loadTemplate($cls, $name, $index);
300        }
301    }
302
303    /**
304    * Finds a template by name.
305    *
306    * @param string  $name  The template name
307    * @return string
308    * @throws \Twig\Error\LoaderError
309    */
310    public function findTemplate($name)
311    {
312        if (strpos($name, '@') === false)
313        {
314            foreach ($this->getNamespaceLookUpOrder() as $namespace)
315            {
316                try
317                {
318                    if ($namespace === '__main__')
319                    {
320                        return parent::getLoader()->getCacheKey($name);
321                    }
322
323                    return parent::getLoader()->getCacheKey('@' . $namespace . '/' . $name);
324                }
325                catch (\Twig\Error\LoaderError $e)
326                {
327                }
328            }
329
330            // We were unable to load any templates
331            throw $e;
332        }
333        else
334        {
335            return parent::getLoader()->getCacheKey($name);
336        }
337    }
338}