diff options
Diffstat (limited to 'phpBB/phpbb/template')
28 files changed, 703 insertions, 547 deletions
| diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php index 7c322cd971..0e0b6b4782 100644 --- a/phpBB/phpbb/template/asset.php +++ b/phpBB/phpbb/template/asset.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template; +  /**  * @ignore  */ @@ -15,17 +17,22 @@ if (!defined('IN_PHPBB'))  	exit;  } -class phpbb_template_asset +class asset  {  	protected $components = array(); +	/** @var \phpbb\filesystem **/ +	protected $phpbb_filesystem; +  	/**  	* Constructor  	*  	* @param string $url URL  	*/ -	public function __construct($url) +	public function __construct($url, \phpbb\filesystem $phpbb_filesystem)  	{ +		$this->phpbb_filesystem = $phpbb_filesystem; +  		$this->set_url($url);  	} @@ -112,7 +119,7 @@ class phpbb_template_asset  	*/  	public function get_url()  	{ -		return $this->join_url($this->components); +		return $this->phpbb_filesystem->update_web_root_path($this->join_url($this->components));  	}  	/** diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php new file mode 100644 index 0000000000..86868707f0 --- /dev/null +++ b/phpBB/phpbb/template/base.php @@ -0,0 +1,150 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\template; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +abstract class base implements template +{ +	/** +	* Template context. +	* Stores template data used during template rendering. +	* +	* @var \phpbb\template\context +	*/ +	protected $context; + +	/** +	* Array of filenames assigned to set_filenames +	* +	* @var array +	*/ +	protected $filenames = array(); + +	/** +	* {@inheritdoc} +	*/ +	public function set_filenames(array $filename_array) +	{ +		$this->filenames = array_merge($this->filenames, $filename_array); + +		return $this; +	} + +	/** +	* Get a filename from the handle +	* +	* @param string $handle +	* @return string +	*/ +	protected function get_filename_from_handle($handle) +	{ +		return (isset($this->filenames[$handle])) ? $this->filenames[$handle] : $handle; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function destroy() +	{ +		$this->context->clear(); + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function destroy_block_vars($blockname) +	{ +		$this->context->destroy_block_vars($blockname); + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function assign_vars(array $vararray) +	{ +		foreach ($vararray as $key => $val) +		{ +			$this->assign_var($key, $val); +		} + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function assign_var($varname, $varval) +	{ +		$this->context->assign_var($varname, $varval); + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function append_var($varname, $varval) +	{ +		$this->context->append_var($varname, $varval); + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function assign_block_vars($blockname, array $vararray) +	{ +		$this->context->assign_block_vars($blockname, $vararray); + +		return $this; +	} + +	/** +	* {@inheritdoc} +	*/ +	public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') +	{ +		return $this->context->alter_block_array($blockname, $vararray, $key, $mode); +	} + +	/** +	* Calls hook if any is defined. +	* +	* @param string $handle Template handle being displayed. +	* @param string $method Method name of the caller. +	*/ +	protected function call_hook($handle, $method) +	{ +		global $phpbb_hook; + +		if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, $method), $handle, $this)) +		{ +			if ($phpbb_hook->hook_return(array(__CLASS__, $method))) +			{ +				$result = $phpbb_hook->hook_return_result(array(__CLASS__, $method)); +				return array($result); +			} +		} + +		return false; +	} +} diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index c5ce7422b9..24234c1e4a 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template; +  /**  * @ignore  */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB'))  *  * @package phpBB3  */ -class phpbb_template_context +class context  {  	/**  	* variable that holds all the data we'll be substituting into @@ -86,7 +88,7 @@ class phpbb_template_context  	* Returns a reference to template data array.  	*  	* This function is public so that template renderer may invoke it. -	* Users should alter template variables via functions in phpbb_template. +	* Users should alter template variables via functions in \phpbb\template\template.  	*  	* Note: modifying returned array will affect data stored in the context.  	* @@ -223,7 +225,7 @@ class phpbb_template_context  	* @param	string	$mode		Mode to execute (valid modes are 'insert' and 'change')  	*  	*	If insert, the vararray is inserted at the given position (position counting from zero). -	*	If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). +	*	If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new \value).  	*  	* Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)  	* and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) diff --git a/phpBB/phpbb/template/locator.php b/phpBB/phpbb/template/locator.php deleted file mode 100644 index f6fd20bcc2..0000000000 --- a/phpBB/phpbb/template/locator.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ -	exit; -} - - -/** -* Resource locator interface. -* -* Objects implementing this interface maintain mapping from template handles -* to source template file paths and locate templates. -* -* Locates style files. -* -* Resource locator is aware of styles tree, and can return actual -* filesystem paths (i.e., the "child" style or the "parent" styles) -* depending on what files exist. -* -* Root paths stored in locator are paths to style directories. Templates are -* stored in subdirectory that $template_path points to. -* -* @package phpBB3 -*/ -interface phpbb_template_locator -{ -	/** -	* Sets the template filenames for handles. $filename_array -	* should be a hash of handle => filename pairs. -	* -	* @param array $filename_array Should be a hash of handle => filename pairs. -	*/ -	public function set_filenames(array $filename_array); - -	/** -	* Determines the filename for a template handle. -	* -	* The filename comes from array used in a set_filenames call, -	* which should have been performed prior to invoking this function. -	* Return value is a file basename (without path). -	* -	* @param $handle string Template handle -	* @return string Filename corresponding to the template handle -	*/ -	public function get_filename_for_handle($handle); - -	/** -	* Determines the source file path for a template handle without -	* regard for styles tree. -	* -	* This function returns the path in "primary" style directory -	* corresponding to the given template handle. That path may or -	* may not actually exist on the filesystem. Because this function -	* does not perform stat calls to determine whether the path it -	* returns actually exists, it is faster than get_source_file_for_handle. -	* -	* Use get_source_file_for_handle to obtain the actual path that is -	* guaranteed to exist (which might come from the parent style -	* directory if primary style has parent styles). -	* -	* This function will trigger an error if the handle was never -	* associated with a template file via set_filenames. -	* -	* @param $handle string Template handle -	* @return string Path to source file path in primary style directory -	*/ -	public function get_virtual_source_file_for_handle($handle); - -	/** -	* Determines the source file path for a template handle, accounting -	* for styles tree and verifying that the path exists. -	* -	* This function returns the actual path that may be compiled for -	* the specified template handle. It will trigger an error if -	* the template handle was never associated with a template path -	* via set_filenames or if the template file does not exist on the -	* filesystem. -	* -	* Use get_virtual_source_file_for_handle to just resolve a template -	* handle to a path without any filesystem or styles tree checks. -	* -	* @param string $handle Template handle (i.e. "friendly" template name) -	* @param bool $find_all If true, each root path will be checked and function -	*				will return array of files instead of string and will not -	*				trigger a error if template does not exist -	* @return string Source file path -	*/ -	public function get_source_file_for_handle($handle, $find_all = false); - -	/** -	* Obtains a complete filesystem path for a file in a style. -	* -	* This function traverses the style tree (selected style and -	* its parents in order, if inheritance is being used) and finds -	* the first file on the filesystem matching specified relative path, -	* or the first of the specified paths if more than one path is given. -	* -	* This function can be used to determine filesystem path of any -	* file under any style, with the consequence being that complete -	* relative to the style directory path must be provided as an argument. -	* -	* In particular, this function can be used to locate templates -	* and javascript files. -	* -	* For locating templates get_first_template_location should be used -	* as it prepends the configured template path to the template basename. -	* -	* Note: "selected style" is whatever style the style resource locator -	* is configured for. -	* -	* The return value then will be a path, relative to the current -	* directory or absolute, to the first existing file in the selected -	* style or its closest parent. -	* -	* If the selected style does not have the file being searched, -	* (and if inheritance is involved, none of the parents have it either), -	* false will be returned. -	* -	* Multiple files can be specified, in which case the first file in -	* the list that can be found on the filesystem is returned. -	* -	* If multiple files are specified and inheritance is involved, -	* first each of the specified files is checked in the selected style, -	* then each of the specified files is checked in the immediate parent, -	* etc. -	* -	* Specifying true for $return_default will cause the function to -	* return the first path which was checked for existence in the event -	* that the template file was not found, instead of false. -	* This is always a path in the selected style itself, not any of its -	* parents. -	* -	* If $return_full_path is false, then instead of returning a usable -	* path (when the file is found) the file's path relative to the style -	* directory will be returned. This is the same path as was given to -	* the function as a parameter. This can be used to check which of the -	* files specified in $files exists. Naturally this requires passing -	* more than one file in $files. -	* -	* @param array $files List of files to locate. -	* @param bool $return_default Determines what to return if file does not -	*				exist. If true, function will return location where file is -	*				supposed to be. If false, function will return false. -	* @param bool $return_full_path If true, function will return full path -	*				to file. If false, function will return file name. This -	*				parameter can be used to check which one of set of files -	*				is available. -	* @return string or boolean Source file path if file exists or $return_default is -	*				true. False if file does not exist and $return_default is false -	*/ -	public function get_first_file_location($files, $return_default = false, $return_full_path = true); -} diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 89a01e924d..cf38bba522 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template; +  /**  * @ignore  */ @@ -15,13 +17,13 @@ if (!defined('IN_PHPBB'))  	exit;  } -interface phpbb_template +interface template  {  	/**  	* Clear the cache  	* -	* @return phpbb_template +	* @return \phpbb\template\template  	*/  	public function clear_cache(); @@ -29,24 +31,42 @@ interface phpbb_template  	* Sets the template filenames for handles.  	*  	* @param array $filename_array Should be a hash of handle => filename pairs. -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function set_filenames(array $filename_array);  	/** -	* Sets the style names/paths corresponding to style hierarchy being compiled -	* and/or rendered. +	* Get the style tree of the style preferred by the current user +	* +	* @return array Style tree, most specific first +	*/ +	public function get_user_style(); + +	/** +	* Set style location based on (current) user's chosen style. +	* +	* @param array $style_directories The directories to add style paths for +	* 	E.g. array('ext/foo/bar/styles', 'styles') +	* 	Default: array('styles') (phpBB's style directory) +	* @return \phpbb\template\template $this +	*/ +	public function set_style($style_directories = array('styles')); + +	/** +	* Set custom style location (able to use directory outside of phpBB). +	* +	* Note: Templates are still compiled to phpBB's cache directory.  	* -	* @param array $style_names List of style names in inheritance tree order -	* @param array $style_paths List of style paths in inheritance tree order -	* @return phpbb_template $this +	* @param string|array $names Array of names or string of name of template(s) in inheritance tree order, used by extensions. +	* @param string|array or string $paths Array of style paths, relative to current root directory +	* @return \phpbb\template\template $this  	*/ -	public function set_style_names(array $style_names, array $style_paths); +	public function set_custom_style($names, $paths);  	/**  	* Clears all variables and blocks assigned to this template.  	* -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function destroy(); @@ -54,7 +74,7 @@ interface phpbb_template  	* Reset/empty complete block  	*  	* @param string $blockname Name of block to destroy -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function destroy_block_vars($blockname); @@ -66,7 +86,7 @@ interface phpbb_template  	* This function calls hooks.  	*  	* @param string $handle Handle to display -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function display($handle); @@ -77,7 +97,7 @@ interface phpbb_template  	* @param string $handle Handle to operate on  	* @param string $template_var Template variable to assign compiled handle to  	* @param bool $return_content If true return compiled handle, otherwise assign to $template_var -	* @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this +	* @return \phpbb\template\template|string if $return_content is true return string of the compiled handle, otherwise return $this  	*/  	public function assign_display($handle, $template_var = '', $return_content = true); @@ -85,7 +105,7 @@ interface phpbb_template  	* Assign key variable pairs from an array  	*  	* @param array $vararray A hash of variable name => value pairs -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function assign_vars(array $vararray); @@ -96,7 +116,7 @@ interface phpbb_template  	*  	* @param string $varname Variable name  	* @param string $varval Value to assign to variable -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function assign_var($varname, $varval); @@ -107,7 +127,7 @@ interface phpbb_template  	*  	* @param string $varname Variable name  	* @param string $varval Value to append to variable -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function append_var($varname, $varval); @@ -115,7 +135,7 @@ interface phpbb_template  	* Assign key variable pairs from an array to a specified block  	* @param string $blockname Name of block to assign $vararray to  	* @param array $vararray A hash of variable name => value pairs -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function assign_block_vars($blockname, array $vararray); @@ -139,7 +159,7 @@ interface phpbb_template  	* @param	string	$mode		Mode to execute (valid modes are 'insert' and 'change')  	*  	*	If insert, the vararray is inserted at the given position (position counting from zero). -	*	If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). +	*	If change, the current block gets merged with the vararray (resulting in new \key/value pairs be added and existing keys be replaced by the new \value).  	*  	* Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)  	* and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) diff --git a/phpBB/phpbb/template/twig/definition.php b/phpBB/phpbb/template/twig/definition.php index 6557b209eb..2490a43f81 100644 --- a/phpBB/phpbb/template/twig/definition.php +++ b/phpBB/phpbb/template/twig/definition.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig; +  /**  * @ignore  */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB'))  /**  * This class holds all DEFINE variables from the current page load  */ -class phpbb_template_twig_definition +class definition  {  	/** @var array **/  	protected $definitions = array(); @@ -39,7 +41,7 @@ class phpbb_template_twig_definition  	*  	* @param string $name  	* @param mixed $value -	* @return phpbb_template_twig_definition +	* @return \phpbb\template\twig\definition  	*/  	public function set($name, $value)  	{ @@ -53,7 +55,7 @@ class phpbb_template_twig_definition  	*  	* @param string $name  	* @param string $value -	* @return phpbb_template_twig_definition +	* @return \phpbb\template\twig\definition  	*/  	public function append($name, $value)  	{ diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php index b60cd72325..e0ee23dcd9 100644 --- a/phpBB/phpbb/template/twig/environment.php +++ b/phpBB/phpbb/template/twig/environment.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig; +  /**  * @ignore  */ @@ -15,34 +17,44 @@ if (!defined('IN_PHPBB'))  	exit;  } -class phpbb_template_twig_environment extends Twig_Environment +class environment extends \Twig_Environment  {  	/** @var array */  	protected $phpbb_extensions; -	/** @var phpbb_config */ +	/** @var \phpbb\config\config */  	protected $phpbb_config; +	/** @var \phpbb\filesystem */ +	protected $phpbb_filesystem; +  	/** @var string */  	protected $phpbb_root_path; +	/** @var string */ +	protected $web_root_path; +  	/** @var array **/  	protected $namespace_look_up_order = array('__main__');  	/**  	* Constructor  	* -	* @param phpbb_config $phpbb_config +	* @param \phpbb\config\config $phpbb_config  	* @param array $phpbb_extensions Array of enabled extensions (name => path) +	* @param \phpbb\filesystem  	* @param string $phpbb_root_path  	* @param Twig_LoaderInterface $loader  	* @param array $options Array of options to pass to Twig  	*/ -	public function __construct($phpbb_config, $phpbb_extensions, $phpbb_root_path, Twig_LoaderInterface $loader = null, $options = array()) +	public function __construct($phpbb_config, $phpbb_extensions, \phpbb\filesystem $phpbb_filesystem, \Twig_LoaderInterface $loader = null, $options = array())  	{  		$this->phpbb_config = $phpbb_config;  		$this->phpbb_extensions = $phpbb_extensions; -		$this->phpbb_root_path = $phpbb_root_path; + +		$this->phpbb_filesystem = $phpbb_filesystem; +		$this->phpbb_root_path = $this->phpbb_filesystem->get_phpbb_root_path(); +		$this->web_root_path = $this->phpbb_filesystem->get_web_root_path();  		return parent::__construct($loader, $options);  	} @@ -62,7 +74,7 @@ class phpbb_template_twig_environment extends Twig_Environment  	/**  	* Get phpBB config  	* -	* @return phpbb_config +	* @return \phpbb\config\config  	*/  	public function get_phpbb_config()  	{ @@ -80,6 +92,26 @@ class phpbb_template_twig_environment extends Twig_Environment  	}  	/** +	* Get the web root path +	* +	* @return string +	*/ +	public function get_web_root_path() +	{ +		return $this->web_root_path; +	} + +	/** +	* Get the phpbb_filesystem object +	* +	* @return \phpbb\filesystem +	*/ +	public function get_filesystem() +	{ +		return $this->phpbb_filesystem; +	} + +	/**  	* Get the namespace look up order  	*  	* @return array @@ -124,7 +156,7 @@ class phpbb_template_twig_environment extends Twig_Environment  					return parent::loadTemplate('@' . $namespace . '/' . $name, $index);  				} -				catch (Twig_Error_Loader $e) +				catch (\Twig_Error_Loader $e)  				{  				}  			} @@ -137,4 +169,39 @@ class phpbb_template_twig_environment extends Twig_Environment  			return parent::loadTemplate($name, $index);  		}  	} + +	/** +	 * Finds a template by name. +	 * +	 * @param string  $name  The template name +	 * @return string +	 */ +	public function findTemplate($name) +	{ +		if (strpos($name, '@') === false) +		{ +			foreach ($this->getNamespaceLookUpOrder() as $namespace) +			{ +				try +				{ +					if ($namespace === '__main__') +					{ +						return parent::getLoader()->getCacheKey($name); +					} + +					return parent::getLoader()->getCacheKey('@' . $namespace . '/' . $name); +				} +				catch (Twig_Error_Loader $e) +				{ +				} +			} + +			// We were unable to load any templates +			throw $e; +		} +		else +		{ +			return parent::getLoader()->getCacheKey($name); +		} +	}  } diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index c279726434..1ddb97369e 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig; +  /**  * @ignore  */ @@ -15,22 +17,22 @@ if (!defined('IN_PHPBB'))  	exit;  } -class phpbb_template_twig_extension extends Twig_Extension +class extension extends \Twig_Extension  { -	/** @var phpbb_template_context */ +	/** @var \phpbb\template\context */  	protected $context; -	/** @var phpbb_user */ +	/** @var \phpbb\user */  	protected $user;  	/**  	* Constructor  	* -	* @param phpbb_template_context $context -	* @param phpbb_user $user -	* @return phpbb_template_twig_extension +	* @param \phpbb\template\context $context +	* @param \phpbb\user $user +	* @return \phpbb\template\twig\extension  	*/ -	public function __construct(phpbb_template_context $context, $user) +	public function __construct(\phpbb\template\context $context, $user)  	{  		$this->context = $context;  		$this->user = $user; @@ -54,13 +56,13 @@ class phpbb_template_twig_extension extends Twig_Extension  	public function getTokenParsers()  	{  		return array( -			new phpbb_template_twig_tokenparser_define, -			new phpbb_template_twig_tokenparser_include, -			new phpbb_template_twig_tokenparser_includejs, -			new phpbb_template_twig_tokenparser_includecss, -			new phpbb_template_twig_tokenparser_event, -			new phpbb_template_twig_tokenparser_includephp, -			new phpbb_template_twig_tokenparser_php, +			new \phpbb\template\twig\tokenparser\defineparser, +			new \phpbb\template\twig\tokenparser\includeparser, +			new \phpbb\template\twig\tokenparser\includejs, +			new \phpbb\template\twig\tokenparser\includecss, +			new \phpbb\template\twig\tokenparser\event, +			new \phpbb\template\twig\tokenparser\includephp, +			new \phpbb\template\twig\tokenparser\php,  		);  	} @@ -72,8 +74,8 @@ class phpbb_template_twig_extension extends Twig_Extension      public function getFilters()      {  		return array( -			new Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)), -			new Twig_SimpleFilter('addslashes', 'addslashes'), +			new \Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)), +			new \Twig_SimpleFilter('addslashes', 'addslashes'),  		);      } @@ -85,7 +87,7 @@ class phpbb_template_twig_extension extends Twig_Extension      public function getFunctions()      {  		return array( -			new Twig_SimpleFunction('lang', array($this, 'lang')), +			new \Twig_SimpleFunction('lang', array($this, 'lang')),  		);  	} @@ -102,26 +104,26 @@ class phpbb_template_twig_extension extends Twig_Extension  			),  			array(  				// precedence settings are copied from similar operators in Twig core extension -				'||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), -				'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), -				'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'neq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'<>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'neq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'<>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), -				'===' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_equalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'!==' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_notequalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'===' => array('precedence' => 20, 'class' => '\phpbb\template\twig\node\expression\binary\equalequal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'!==' => array('precedence' => 20, 'class' => '\phpbb\template\twig\node\expression\binary\notequalequal', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), -				'gt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'gte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'ge' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'lt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'lte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), -				'le' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'gt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'gte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'ge' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'lt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'lte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), +				'le' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT), -				'mod' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), +				'mod' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => \Twig_ExpressionParser::OPERATOR_LEFT),  			),  		);      } @@ -137,7 +139,7 @@ class phpbb_template_twig_extension extends Twig_Extension  	 *  	 * @return mixed The sliced variable  	 */ -	function loop_subset(Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false) +	function loop_subset(\Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false)  	{  		// We do almost the same thing as Twig's slice (array_slice), except when $end is positive  		if ($end >= 1) diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php index 3534311b7a..d832fbf84e 100644 --- a/phpBB/phpbb/template/twig/lexer.php +++ b/phpBB/phpbb/template/twig/lexer.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig; +  /**  * @ignore  */ @@ -15,7 +17,7 @@ if (!defined('IN_PHPBB'))  	exit;  } -class phpbb_template_twig_lexer extends Twig_Lexer +class lexer extends \Twig_Lexer  {  	public function tokenize($code, $filename = null)  	{ @@ -75,7 +77,7 @@ class phpbb_template_twig_lexer extends Twig_Lexer  		// Fix tokens that may have inline variables (e.g. <!-- DEFINE $TEST = '{FOO}')  		$code = $this->fix_inline_variable_tokens(array( -			'DEFINE.+=', +			'DEFINE \$[a-zA-Z0-9_]+ =',  			'INCLUDE',  			'INCLUDEPHP',  			'INCLUDEJS', @@ -130,7 +132,7 @@ class phpbb_template_twig_lexer extends Twig_Lexer  			// E.g. 'asdf'"' -> asdf'"  			// E.g. "asdf'"" -> asdf'"  			// E.g. 'asdf'" -> 'asdf'" -			$matches[2] = preg_replace('#^([\'"])?(.+?)\1$#', '$2', $matches[2]); +			$matches[2] = preg_replace('#^([\'"])?(.*?)\1$#', '$2', $matches[2]);  			// Replace template variables with start/end to parse variables (' ~ TEST ~ '.html)  			$matches[2] = preg_replace('#{([a-zA-Z0-9_\.$]+)}#', "'~ \$1 ~'", $matches[2]); @@ -161,6 +163,9 @@ class phpbb_template_twig_lexer extends Twig_Lexer  			$subset = trim(substr($matches[2], 1, -1)); // Remove parenthesis  			$body = $matches[3]; +			// Replace <!-- BEGINELSE --> +			$body = str_replace('<!-- BEGINELSE -->', '{% else %}', $body); +  			// Is the designer wanting to call another loop in a loop?  			// <!-- BEGIN loop -->  			// <!-- BEGIN !loop2 --> @@ -205,9 +210,6 @@ class phpbb_template_twig_lexer extends Twig_Lexer  			return "{% for {$name} in {$parent}{$name}{$subset} %}{$body}{% endfor %}";  		}; -		// Replace <!-- BEGINELSE --> correctly, only needs to be done once -		$code = str_replace('<!-- BEGINELSE -->', '{% else %}', $code); -  		return preg_replace_callback('#<!-- BEGIN ([!a-zA-Z0-9_]+)(\([0-9,\-]+\))? -->(.+?)<!-- END \1 -->#s', $callback, $code);  	} @@ -219,25 +221,28 @@ class phpbb_template_twig_lexer extends Twig_Lexer  	*/  	protected function fix_if_tokens($code)  	{ +		// Replace ELSE IF with ELSEIF +		$code = preg_replace('#<!-- ELSE IF (.+?) -->#', '<!-- ELSEIF $1 -->', $code); + +		// Replace our "div by" with Twig's divisibleby (Twig does not like test names with spaces) +		$code = preg_replace('# div by ([0-9]+)#', ' divisibleby($1)', $code); +  		$callback = function($matches)  		{  			$inner = $matches[2];  			// Replace $TEST with definition.TEST -			$inner = preg_replace('#\s\$([a-zA-Z_0-9]+)#', ' definition.$1', $inner); +			$inner = preg_replace('#(\s\(*!?)\$([a-zA-Z_0-9]+)#', '$1definition.$2', $inner);  			// Replace .foo with loops.foo|length -			$inner = preg_replace('#\s\.([a-zA-Z_0-9]+)([^a-zA-Z_0-9\.])#', ' loops.$1|length$2', $inner); +			$inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9]+)([^a-zA-Z_0-9\.])#', '$1loops.$2|length$3', $inner);  			// Replace .foo.bar with foo.bar|length -			$inner = preg_replace('#\s\.([a-zA-Z_0-9\.]+)([^a-zA-Z_0-9\.])#', ' $1|length$2', $inner); +			$inner = preg_replace('#(\s\(*!?)\.([a-zA-Z_0-9\.]+)([^a-zA-Z_0-9\.])#', '$1$2|length$3', $inner);  			return "<!-- {$matches[1]}IF{$inner}-->";  		}; -		// Replace our "div by" with Twig's divisibleby (Twig does not like test names with spaces) -		$code = preg_replace('# div by ([0-9]+)#', ' divisibleby($1)', $code); - -		return preg_replace_callback('#<!-- (ELSE)?IF((.*)[\s][\$|\.|!]([^\s]+)(.*))-->#', $callback, $code); +		return preg_replace_callback('#<!-- (ELSE)?IF((.*?) \(*!?[\$|\.]([^\s]+)(.*?))-->#', $callback, $code);  	}  	/** @@ -261,10 +266,10 @@ class phpbb_template_twig_lexer extends Twig_Lexer  		*/  		// Replace <!-- DEFINE $NAME with {% DEFINE definition.NAME -		$code = preg_replace('#<!-- DEFINE \$(.*)-->#', '{% DEFINE $1 %}', $code); +		$code = preg_replace('#<!-- DEFINE \$(.*?) -->#', '{% DEFINE $1 %}', $code);  		// Changing UNDEFINE NAME to DEFINE NAME = null to save from creating an extra token parser/node -		$code = preg_replace('#<!-- UNDEFINE \$(.*)-->#', '{% DEFINE $1= null %}', $code); +		$code = preg_replace('#<!-- UNDEFINE \$(.*?)-->#', '{% DEFINE $1= null %}', $code);  		// Replace all of our variables, {$VARNAME}, with Twig style, {{ definition.VARNAME }}  		$code = preg_replace('#{\$([a-zA-Z0-9_\.]+)}#', '{{ definition.$1 }}', $code); diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php new file mode 100644 index 0000000000..910061dc0f --- /dev/null +++ b/phpBB/phpbb/template/twig/loader.php @@ -0,0 +1,152 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\template\twig; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Twig Template loader +* @package phpBB3 +*/ +class loader extends \Twig_Loader_Filesystem +{ +	protected $safe_directories = array(); + +	/** +	* Set safe directories +	* +	* @param array $directories Array of directories that are safe (empty to clear) +	* @return Twig_Loader_Filesystem +	*/ +	public function setSafeDirectories($directories = array()) +	{ +		$this->safe_directories = array(); + +		if (!empty($directories)) +		{ +			foreach ($directories as $directory) +			{ +				$this->addSafeDirectory($directory); +			} +		} + +		return $this; +	} + +	/** +	* Add safe directory +	* +	* @param string $directory Directory that should be added +	* @return Twig_Loader_Filesystem +	*/ +	public function addSafeDirectory($directory) +	{ +		$directory = phpbb_realpath($directory); + +		if ($directory !== false) +		{ +			$this->safe_directories[] = $directory; +		} + +		return $this; +	} + +	/** +	* Get current safe directories +	* +	* @return array +	*/ +	public function getSafeDirectories() +	{ +		return $this->safe_directories; +	} + +	/** +	* Override for parent::validateName() +	* +	* This is done because we added support for safe directories, and when Twig +	*	findTemplate() is called, validateName() is called first, which would +	*	always throw an exception if the file is outside of the configured +	*	template directories. +	*/ +	protected function validateName($name) +	{ +		return; +	} + +	/** +	* Find the template +	* +	* Override for Twig_Loader_Filesystem::findTemplate to add support +	*	for loading from safe directories. +	*/ +	protected function findTemplate($name) +	{ +		$name = (string) $name; + +		// normalize name +		$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/')); + +		// If this is in the cache we can skip the entire process below +		//	as it should have already been validated +		if (isset($this->cache[$name])) { +			return $this->cache[$name]; +		} + +		// First, find the template name. The override above of validateName +		//	causes the validateName process to be skipped for this call +		$file = parent::findTemplate($name); + +		try +		{ +			// Try validating the name (which may throw an exception) +			parent::validateName($name); +		} +		catch (Twig_Error_Loader $e) +		{ +			if (strpos($e->getRawMessage(), 'Looks like you try to load a template outside configured directories') === 0) +			{ +				// Ok, so outside of the configured template directories, we +				//	can now check if we're within a "safe" directory + +				// Find the real path of the directory the file is in +				$directory = phpbb_realpath(dirname($file)); + +				if ($directory === false) +				{ +					// Some sort of error finding the actual path, must throw the exception +					throw $e; +				} + +				foreach ($this->safe_directories as $safe_directory) +				{ +					if (strpos($directory, $safe_directory) === 0) +					{ +						// The directory being loaded is below a directory +						// that is "safe". We're good to load it! +						return $file; +					} +				} +			} + +			// Not within any safe directories +			throw $e; +		} + +		// No exception from validateName, safe to load. +		return $file; +	} +} diff --git a/phpBB/phpbb/template/twig/node/define.php b/phpBB/phpbb/template/twig/node/definenode.php index fcb19cc773..ec084d0f7d 100644 --- a/phpBB/phpbb/template/twig/node/define.php +++ b/phpBB/phpbb/template/twig/node/definenode.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node; +  /**  * @ignore  */ @@ -16,9 +18,9 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_define extends Twig_Node +class definenode extends \Twig_Node  { -	public function __construct($capture, Twig_NodeInterface $name, Twig_NodeInterface $value, $lineno, $tag = null) +	public function __construct($capture, \Twig_NodeInterface $name, \Twig_NodeInterface $value, $lineno, $tag = null)  	{  		parent::__construct(array('name' => $name, 'value' => $value), array('capture' => $capture, 'safe' => false), $lineno, $tag);  	} @@ -28,7 +30,7 @@ class phpbb_template_twig_node_define extends Twig_Node  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); @@ -38,7 +40,7 @@ class phpbb_template_twig_node_define extends Twig_Node  				->subcompile($this->getNode('value'))  			; -			$compiler->write("\$value = ('' === \$value = ob_get_clean()) ? '' : new Twig_Markup(\$value, \$this->env->getCharset());\n"); +			$compiler->write("\$value = ('' === \$value = ob_get_clean()) ? '' : new \Twig_Markup(\$value, \$this->env->getCharset());\n");  		}  		else  		{ diff --git a/phpBB/phpbb/template/twig/node/event.php b/phpBB/phpbb/template/twig/node/event.php index c94e5fdf20..202db775ee 100644 --- a/phpBB/phpbb/template/twig/node/event.php +++ b/phpBB/phpbb/template/twig/node/event.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node; +  /**  * @ignore  */ @@ -16,9 +18,9 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_event extends Twig_Node +class event extends \Twig_Node  { -	/**  +	/**  	 * The subdirectory in which all template listener files must be placed  	 * @var string  	 */ @@ -27,7 +29,7 @@ class phpbb_template_twig_node_event extends Twig_Node  	/** @var Twig_Environment */  	protected $environment; -	public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null) +	public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null)  	{  		$this->environment = $environment; @@ -39,7 +41,7 @@ class phpbb_template_twig_node_event extends Twig_Node  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); diff --git a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php index 8ec2069114..48d8b814b8 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/equalequal.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node\expression\binary; +  /**  * @ignore  */ @@ -16,9 +18,9 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_expression_binary_equalequal extends Twig_Node_Expression_Binary +class equalequal extends \Twig_Node_Expression_Binary  { -	public function operator(Twig_Compiler $compiler) +	public function operator(\Twig_Compiler $compiler)  	{  		return $compiler->raw('===');  	} diff --git a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php index 96f32c502e..87585dfb4c 100644 --- a/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php +++ b/phpBB/phpbb/template/twig/node/expression/binary/notequalequal.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node\expression\binary; +  /**  * @ignore  */ @@ -16,9 +18,9 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_expression_binary_notequalequal extends Twig_Node_Expression_Binary +class notequalequal extends \Twig_Node_Expression_Binary  { -	public function operator(Twig_Compiler $compiler) +	public function operator(\Twig_Compiler $compiler)  	{  		return $compiler->raw('!==');  	} diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 1cab416c79..f15fd6296b 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -7,12 +7,14 @@  *  */ -abstract class phpbb_template_twig_node_includeasset extends Twig_Node +namespace phpbb\template\twig\node; + +abstract class includeasset extends \Twig_Node  {  	/** @var Twig_Environment */  	protected $environment; -	public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null) +	public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null)  	{  		$this->environment = $environment; @@ -23,7 +25,7 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); @@ -33,17 +35,17 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node  			->write("\$asset_file = ")  			->subcompile($this->getNode('expr'))  			->raw(";\n") -			->write("\$asset = new phpbb_template_asset(\$asset_file);\n") +			->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_filesystem());\n")  			->write("if (substr(\$asset_file, 0, 2) !== './' && \$asset->is_relative()) {\n")  			->indent()  				->write("\$asset_path = \$asset->get_path();")  				->write("\$local_file = \$this->getEnvironment()->get_phpbb_root_path() . \$asset_path;\n")  				->write("if (!file_exists(\$local_file)) {\n")  				->indent() -					->write("\$local_file = \$this->getEnvironment()->getLoader()->getCacheKey(\$asset_path);\n") +					->write("\$local_file = \$this->getEnvironment()->findTemplate(\$asset_path);\n")  					->write("\$asset->set_path(\$local_file, true);\n")  				->outdent() -				->write("\$asset->add_assets_version({$config['assets_version']});\n") +				->write("\$asset->add_assets_version('{$config['assets_version']}');\n")  				->write("\$asset_file = \$asset->get_url();\n")  				->write("}\n")  			->outdent() @@ -71,5 +73,5 @@ abstract class phpbb_template_twig_node_includeasset extends Twig_Node  	* @param Twig_Compiler A Twig_Compiler instance  	* @return null  	*/ -	abstract protected function append_asset(Twig_Compiler $compiler); +	abstract protected function append_asset(\Twig_Compiler $compiler);  } diff --git a/phpBB/phpbb/template/twig/node/includecss.php b/phpBB/phpbb/template/twig/node/includecss.php index a9d9b46d69..deb279fa4a 100644 --- a/phpBB/phpbb/template/twig/node/includecss.php +++ b/phpBB/phpbb/template/twig/node/includecss.php @@ -7,7 +7,9 @@  *  */ -class phpbb_template_twig_node_includecss extends phpbb_template_twig_node_includeasset +namespace phpbb\template\twig\node; + +class includecss extends \phpbb\template\twig\node\includeasset  {  	/**  	* {@inheritdoc} @@ -20,7 +22,7 @@ class phpbb_template_twig_node_includecss extends phpbb_template_twig_node_inclu  	/**  	* {@inheritdoc}  	*/ -	public function append_asset(Twig_Compiler $compiler) +	public function append_asset(\Twig_Compiler $compiler)  	{  		$compiler  			->raw("<link href=\"' . ") diff --git a/phpBB/phpbb/template/twig/node/includejs.php b/phpBB/phpbb/template/twig/node/includejs.php index 2b4b55fb0a..696b640eac 100644 --- a/phpBB/phpbb/template/twig/node/includejs.php +++ b/phpBB/phpbb/template/twig/node/includejs.php @@ -7,7 +7,9 @@  *  */ -class phpbb_template_twig_node_includejs extends phpbb_template_twig_node_includeasset +namespace phpbb\template\twig\node; + +class includejs extends \phpbb\template\twig\node\includeasset  {  	/**  	* {@inheritdoc} @@ -20,7 +22,7 @@ class phpbb_template_twig_node_includejs extends phpbb_template_twig_node_includ  	/**  	* {@inheritdoc}  	*/ -	protected function append_asset(Twig_Compiler $compiler) +	protected function append_asset(\Twig_Compiler $compiler)  	{  		$config = $this->environment->get_phpbb_config(); diff --git a/phpBB/phpbb/template/twig/node/include.php b/phpBB/phpbb/template/twig/node/includenode.php index 5c6ae1bbcf..77fe7f3acb 100644 --- a/phpBB/phpbb/template/twig/node/include.php +++ b/phpBB/phpbb/template/twig/node/includenode.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node; +  /**  * @ignore  */ @@ -16,14 +18,14 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_include extends Twig_Node_Include +class includenode extends \Twig_Node_Include  {  	/**  	 * Compiles the node to PHP.  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); diff --git a/phpBB/phpbb/template/twig/node/includephp.php b/phpBB/phpbb/template/twig/node/includephp.php index dbe54f0e1a..4024cf0cc8 100644 --- a/phpBB/phpbb/template/twig/node/includephp.php +++ b/phpBB/phpbb/template/twig/node/includephp.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node; +  /**  * @ignore  */ @@ -16,12 +18,12 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_includephp extends Twig_Node +class includephp extends \Twig_Node  {  	/** @var Twig_Environment */  	protected $environment; -	public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $ignoreMissing = false, $lineno, $tag = null) +	public function __construct(\Twig_Node_Expression $expr, \phpbb\template\twig\environment $environment, $ignoreMissing = false, $lineno, $tag = null)  	{  		$this->environment = $environment; @@ -33,7 +35,7 @@ class phpbb_template_twig_node_includephp extends Twig_Node  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); @@ -80,7 +82,7 @@ class phpbb_template_twig_node_includephp extends Twig_Node  		if ($this->getAttribute('ignore_missing')) {  			$compiler  				->outdent() -				->write("} catch (Twig_Error_Loader \$e) {\n") +				->write("} catch (\Twig_Error_Loader \$e) {\n")  				->indent()  				->write("// ignore missing template\n")  				->outdent() diff --git a/phpBB/phpbb/template/twig/node/php.php b/phpBB/phpbb/template/twig/node/php.php index c11539ea7f..b37759303d 100644 --- a/phpBB/phpbb/template/twig/node/php.php +++ b/phpBB/phpbb/template/twig/node/php.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\node; +  /**  * @ignore  */ @@ -16,12 +18,12 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_node_php extends Twig_Node +class php extends \Twig_Node  {  	/** @var Twig_Environment */  	protected $environment; -	public function __construct(Twig_Node_Text $text, phpbb_template_twig_environment $environment, $lineno, $tag = null) +	public function __construct(\Twig_Node_Text $text, \phpbb\template\twig\environment $environment, $lineno, $tag = null)  	{  		$this->environment = $environment; @@ -33,7 +35,7 @@ class phpbb_template_twig_node_php extends Twig_Node  	 *  	 * @param Twig_Compiler A Twig_Compiler instance  	 */ -	public function compile(Twig_Compiler $compiler) +	public function compile(\Twig_Compiler $compiler)  	{  		$compiler->addDebugInfo($this); diff --git a/phpBB/phpbb/template/twig/tokenparser/define.php b/phpBB/phpbb/template/twig/tokenparser/defineparser.php index 4ea15388c4..688afec191 100644 --- a/phpBB/phpbb/template/twig/tokenparser/define.php +++ b/phpBB/phpbb/template/twig/tokenparser/defineparser.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_define extends Twig_TokenParser +class defineparser extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -25,31 +27,31 @@ class phpbb_template_twig_tokenparser_define extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$lineno = $token->getLine();  		$stream = $this->parser->getStream();  		$name = $this->parser->getExpressionParser()->parseExpression();  		$capture = false; -		if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) { +		if ($stream->test(\Twig_Token::OPERATOR_TYPE, '=')) {  			$stream->next();  			$value = $this->parser->getExpressionParser()->parseExpression(); -			$stream->expect(Twig_Token::BLOCK_END_TYPE); +			$stream->expect(\Twig_Token::BLOCK_END_TYPE);  		} else {  			$capture = true; -			$stream->expect(Twig_Token::BLOCK_END_TYPE); +			$stream->expect(\Twig_Token::BLOCK_END_TYPE);  			$value = $this->parser->subparse(array($this, 'decideBlockEnd'), true); -			$stream->expect(Twig_Token::BLOCK_END_TYPE); +			$stream->expect(\Twig_Token::BLOCK_END_TYPE);  		} -		return new phpbb_template_twig_node_define($capture, $name, $value, $lineno, $this->getTag()); +		return new \phpbb\template\twig\node\definenode($capture, $name, $value, $lineno, $this->getTag());  	} -	public function decideBlockEnd(Twig_Token $token) +	public function decideBlockEnd(\Twig_Token $token)  	{  		return $token->test('ENDDEFINE');  	} diff --git a/phpBB/phpbb/template/twig/tokenparser/event.php b/phpBB/phpbb/template/twig/tokenparser/event.php index e4dddd6dcc..7cf4000909 100644 --- a/phpBB/phpbb/template/twig/tokenparser/event.php +++ b/phpBB/phpbb/template/twig/tokenparser/event.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_event extends Twig_TokenParser +class event extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -25,14 +27,14 @@ class phpbb_template_twig_tokenparser_event extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$expr = $this->parser->getExpressionParser()->parseExpression();  		$stream = $this->parser->getStream(); -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new phpbb_template_twig_node_event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includecss.php b/phpBB/phpbb/template/twig/tokenparser/includecss.php index 6c24dda647..7bf4c610b1 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includecss.php +++ b/phpBB/phpbb/template/twig/tokenparser/includecss.php @@ -7,7 +7,9 @@  *  */ -class phpbb_template_twig_tokenparser_includecss extends Twig_TokenParser +namespace phpbb\template\twig\tokenparser; + +class includecss extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -16,14 +18,14 @@ class phpbb_template_twig_tokenparser_includecss extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$expr = $this->parser->getExpressionParser()->parseExpression();  		$stream = $this->parser->getStream(); -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new phpbb_template_twig_node_includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includejs.php b/phpBB/phpbb/template/twig/tokenparser/includejs.php index b02b2f89ba..30a99f3279 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includejs.php +++ b/phpBB/phpbb/template/twig/tokenparser/includejs.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_includejs extends Twig_TokenParser +class includejs extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -25,14 +27,14 @@ class phpbb_template_twig_tokenparser_includejs extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$expr = $this->parser->getExpressionParser()->parseExpression();  		$stream = $this->parser->getStream(); -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new phpbb_template_twig_node_includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/include.php b/phpBB/phpbb/template/twig/tokenparser/includeparser.php index 520f9fd1a0..715c0ec84d 100644 --- a/phpBB/phpbb/template/twig/tokenparser/include.php +++ b/phpBB/phpbb/template/twig/tokenparser/includeparser.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include +class includeparser extends \Twig_TokenParser_Include  {  	/**  	 * Parses a token and returns a node. @@ -25,13 +27,13 @@ class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	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()); +		return new \phpbb\template\twig\node\includenode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/includephp.php b/phpBB/phpbb/template/twig/tokenparser/includephp.php index 13fe6de8a6..d906837590 100644 --- a/phpBB/phpbb/template/twig/tokenparser/includephp.php +++ b/phpBB/phpbb/template/twig/tokenparser/includephp.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_includephp extends Twig_TokenParser +class includephp extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -25,23 +27,23 @@ class phpbb_template_twig_tokenparser_includephp extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$expr = $this->parser->getExpressionParser()->parseExpression();  		$stream = $this->parser->getStream();  		$ignoreMissing = false; -		if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) { +		if ($stream->test(\Twig_Token::NAME_TYPE, 'ignore')) {  			$stream->next(); -			$stream->expect(Twig_Token::NAME_TYPE, 'missing'); +			$stream->expect(\Twig_Token::NAME_TYPE, 'missing');  			$ignoreMissing = true;  		} -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new phpbb_template_twig_node_includephp($expr, $this->parser->getEnvironment(), $ignoreMissing, $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\includephp($expr, $this->parser->getEnvironment(), $ignoreMissing, $token->getLine(), $this->getTag());  	}  	/** diff --git a/phpBB/phpbb/template/twig/tokenparser/php.php b/phpBB/phpbb/template/twig/tokenparser/php.php index 197980a59a..e4f70fb9b1 100644 --- a/phpBB/phpbb/template/twig/tokenparser/php.php +++ b/phpBB/phpbb/template/twig/tokenparser/php.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig\tokenparser; +  /**  * @ignore  */ @@ -16,7 +18,7 @@ if (!defined('IN_PHPBB'))  } -class phpbb_template_twig_tokenparser_php extends Twig_TokenParser +class php extends \Twig_TokenParser  {  	/**  	 * Parses a token and returns a node. @@ -25,20 +27,20 @@ class phpbb_template_twig_tokenparser_php extends Twig_TokenParser  	 *  	 * @return Twig_NodeInterface A Twig_NodeInterface instance  	 */ -	public function parse(Twig_Token $token) +	public function parse(\Twig_Token $token)  	{  		$stream = $this->parser->getStream(); -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE);  		$body = $this->parser->subparse(array($this, 'decideEnd'), true); -		$stream->expect(Twig_Token::BLOCK_END_TYPE); +		$stream->expect(\Twig_Token::BLOCK_END_TYPE); -		return new phpbb_template_twig_node_php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag()); +		return new \phpbb\template\twig\node\php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());  	} -	public function decideEnd(Twig_Token $token) +	public function decideEnd(\Twig_Token $token)  	{  		return $token->test('ENDPHP');  	} diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 6cff1bb8e4..2da7405743 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -7,6 +7,8 @@  *  */ +namespace phpbb\template\twig; +  /**  * @ignore  */ @@ -19,16 +21,9 @@ if (!defined('IN_PHPBB'))  * Twig Template class.  * @package phpBB3  */ -class phpbb_template_twig implements phpbb_template +class twig extends \phpbb\template\base  {  	/** -	* Template context. -	* Stores template data used during template rendering. -	* @var phpbb_template_context -	*/ -	protected $context; - -	/**  	* Path of the cache directory for the template  	*  	* Cannot be changed during runtime. @@ -38,16 +33,16 @@ class phpbb_template_twig implements phpbb_template  	private $cachepath = '';  	/** -	* phpBB root path -	* @var string +	* phpBB filesystem +	* @var \phpbb\filesystem  	*/ -	protected $phpbb_root_path; +	protected $phpbb_filesystem;  	/** -	* adm relative path +	* phpBB root path  	* @var string  	*/ -	protected $adm_relative_path; +	protected $phpbb_root_path;  	/**  	* PHP file extension @@ -57,34 +52,24 @@ class phpbb_template_twig implements phpbb_template  	/**  	* phpBB config instance -	* @var phpbb_config +	* @var \phpbb\config\config  	*/  	protected $config;  	/**  	* Current user -	* @var phpbb_user +	* @var \phpbb\user  	*/  	protected $user;  	/**  	* Extension manager.  	* -	* @var phpbb_extension_manager +	* @var \phpbb\extension\manager  	*/  	protected $extension_manager;  	/** -	* Name of the style that the template being compiled and/or rendered -	* belongs to, and its parents, in inheritance tree order. -	* -	* Used to invoke style-specific template events. -	* -	* @var array -	*/ -	protected $style_names; - -	/**  	* Twig Environment  	*  	* @var Twig_Environment @@ -92,42 +77,33 @@ class phpbb_template_twig implements phpbb_template  	protected $twig;  	/** -	* Array of filenames assigned to set_filenames -	* -	* @var array -	*/ -	protected $filenames = array(); - -	/**  	* Constructor.  	* -	* @param string $phpbb_root_path phpBB root path -	* @param string $php_ext php extension (typically 'php') -	* @param phpbb_config $config -	* @param phpbb_user $user -	* @param phpbb_template_context $context template context -	* @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked -	* @param string $adm_relative_path relative path to adm directory +	* @param \phpbb\filesystem $phpbb_filesystem +	* @param \phpbb\config\config $config +	* @param \phpbb\user $user +	* @param \phpbb\template\context $context template context +	* @param \phpbb\extension\manager $extension_manager extension manager, if null then template events will not be invoked  	*/ -	public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null, $adm_relative_path = null) +	public function __construct(\phpbb\filesystem $phpbb_filesystem, $config, $user, \phpbb\template\context $context, \phpbb\extension\manager $extension_manager = null)  	{ -		$this->phpbb_root_path = $phpbb_root_path; -		$this->adm_relative_path = $adm_relative_path; -		$this->php_ext = $php_ext; +		$this->phpbb_filesystem = $phpbb_filesystem; +		$this->phpbb_root_path = $phpbb_filesystem->get_phpbb_root_path(); +		$this->php_ext = $phpbb_filesystem->get_php_ext();  		$this->config = $config;  		$this->user = $user;  		$this->context = $context;  		$this->extension_manager = $extension_manager; -		$this->cachepath = $phpbb_root_path . 'cache/twig/'; +		$this->cachepath = $this->phpbb_root_path . 'cache/twig/';  		// Initiate the loader, __main__ namespace paths will be setup later in set_style_names() -		$loader = new Twig_Loader_Filesystem(''); +		$loader = new \phpbb\template\twig\loader(''); -		$this->twig = new phpbb_template_twig_environment( +		$this->twig = new \phpbb\template\twig\environment(  			$this->config,  			($this->extension_manager) ? $this->extension_manager->all_enabled() : array(), -			$this->phpbb_root_path, +			$this->phpbb_filesystem,  			$loader,  			array(  				'cache'			=> (defined('IN_INSTALL')) ? false : $this->cachepath, @@ -138,21 +114,27 @@ class phpbb_template_twig implements phpbb_template  		);  		$this->twig->addExtension( -			new phpbb_template_twig_extension( +			new \phpbb\template\twig\extension(  				$this->context,  				$this->user  			)  		); -		$lexer = new phpbb_template_twig_lexer($this->twig); +		$lexer = new \phpbb\template\twig\lexer($this->twig);  		$this->twig->setLexer($lexer); + +		// Add admin namespace +		if ($this->phpbb_filesystem->get_adm_relative_path() !== null && is_dir($this->phpbb_root_path . $this->phpbb_filesystem->get_adm_relative_path() . 'style/')) +		{ +			$this->twig->getLoader()->setPaths($this->phpbb_root_path . $this->phpbb_filesystem->get_adm_relative_path() . 'style/', 'admin'); +		}  	}  	/**  	* Clear the cache  	* -	* @return phpbb_template +	* @return \phpbb\template\template  	*/  	public function clear_cache()  	{ @@ -165,51 +147,94 @@ class phpbb_template_twig implements phpbb_template  	}  	/** -	* Sets the template filenames for handles. +	* Get the style tree of the style preferred by the current user  	* -	* @param array $filename_array Should be a hash of handle => filename pairs. -	* @return phpbb_template $this +	* @return array Style tree, most specific first  	*/ -	public function set_filenames(array $filename_array) +	public function get_user_style()  	{ -		$this->filenames = array_merge($this->filenames, $filename_array); +		$style_list = array( +			$this->user->style['style_path'], +		); -		return $this; +		if ($this->user->style['style_parent_id']) +		{ +			$style_list = array_merge($style_list, array_reverse(explode('/', $this->user->style['style_parent_tree']))); +		} + +		return $style_list;  	}  	/** -	* Sets the style names/paths corresponding to style hierarchy being compiled -	* and/or rendered. +	* Set style location based on (current) user's chosen style.  	* -	* @param array $style_names List of style names in inheritance tree order -	* @param array $style_paths List of style paths in inheritance tree order -	* @param bool $is_core True if the style names are the "core" styles for this page load -	* 	Core means the main phpBB template files -	* @return phpbb_template $this +	* @param array $style_directories The directories to add style paths for +	* 	E.g. array('ext/foo/bar/styles', 'styles') +	* 	Default: array('styles') (phpBB's style directory) +	* @return \phpbb\template\template $this  	*/ -	public function set_style_names(array $style_names, array $style_paths, $is_core = false) +	public function set_style($style_directories = array('styles'))  	{ -		$this->style_names = $style_names; +		if ($style_directories !== array('styles') && $this->twig->getLoader()->getPaths('core') === array()) +		{ +			// We should set up the core styles path since not already setup +			$this->set_style(); +		} -		// Set as __main__ namespace -		$this->twig->getLoader()->setPaths($style_paths); +		$names = $this->get_user_style(); -		// Core style namespace from phpbb_style::set_style() -		if ($is_core) +		$paths = array(); +		foreach ($style_directories as $directory)  		{ -			$this->twig->getLoader()->setPaths($style_paths, 'core'); +			foreach ($names as $name) +			{ +				$path = $this->phpbb_root_path . trim($directory, '/') . "/{$name}/"; +				$template_path = $path . 'template/'; + +				if (is_dir($template_path)) +				{ +					// Add the base style directory as a safe directory +					$this->twig->getLoader()->addSafeDirectory($path); + +					$paths[] = $template_path; +				} +			}  		} -		// Add admin namespace -		if (is_dir($this->phpbb_root_path . $this->adm_relative_path . 'style/')) +		// If we're setting up the main phpBB styles directory and the core +		// namespace isn't setup yet, we will set it up now +		if ($style_directories === array('styles') && $this->twig->getLoader()->getPaths('core') === array())  		{ -			$this->twig->getLoader()->setPaths($this->phpbb_root_path . $this->adm_relative_path . 'style/', 'admin'); +			// Set up the core style paths namespace +			$this->twig->getLoader()->setPaths($paths, 'core');  		} +		$this->set_custom_style($names, $paths); + +		return $this; +	} + +	/** +	* Set custom style location (able to use directory outside of phpBB). +	* +	* Note: Templates are still compiled to phpBB's cache directory. +	* +	* @param string|array $names Array of names or string of name of template(s) in inheritance tree order, used by extensions. +	* @param string|array or string $paths Array of style paths, relative to current root directory +	* @return phpbb_template $this +	*/ +	public function set_custom_style($names, $paths) +	{ +		$paths = (is_string($paths)) ? array($paths) : $paths; +		$names = (is_string($names)) ? array($names) : $names; + +		// Set as __main__ namespace +		$this->twig->getLoader()->setPaths($paths); +  		// Add all namespaces for all extensions -		if ($this->extension_manager instanceof phpbb_extension_manager) +		if ($this->extension_manager instanceof \phpbb\extension\manager)  		{ -			$style_names[] = 'all'; +			$names[] = 'all';  			foreach ($this->extension_manager->all_enabled() as $ext_namespace => $ext_path)  			{ @@ -217,13 +242,17 @@ class phpbb_template_twig implements phpbb_template  				$namespace = str_replace('/', '_', $ext_namespace);  				$paths = array(); -				foreach ($style_names as $style_name) +				foreach ($names as $style_name)  				{ -					$ext_style_path = $ext_path . 'styles/' . $style_name . '/template'; +					$ext_style_path = $ext_path . 'styles/' . $style_name . '/'; +					$ext_style_template_path = $ext_style_path . 'template/'; -					if (is_dir($ext_style_path)) +					if (is_dir($ext_style_template_path))  					{ -						$paths[] = $ext_style_path; +						// Add the base style directory as a safe directory +						$this->twig->getLoader()->addSafeDirectory($ext_style_path); + +						$paths[] = $ext_style_template_path;  					}  				} @@ -235,31 +264,6 @@ class phpbb_template_twig implements phpbb_template  	}  	/** -	* Clears all variables and blocks assigned to this template. -	* -	* @return phpbb_template $this -	*/ -	public function destroy() -	{ -		$this->context = array(); - -		return $this; -	} - -	/** -	* Reset/empty complete block -	* -	* @param string $blockname Name of block to destroy -	* @return phpbb_template $this -	*/ -	public function destroy_block_vars($blockname) -	{ -		$this->context->destroy_block_vars($blockname); - -		return $this; -	} - -	/**  	* Display a template for provided handle.  	*  	* The template will be loaded and compiled, if necessary, first. @@ -267,7 +271,7 @@ class phpbb_template_twig implements phpbb_template  	* This function calls hooks.  	*  	* @param string $handle Handle to display -	* @return phpbb_template $this +	* @return \phpbb\template\template $this  	*/  	public function display($handle)  	{ @@ -283,35 +287,13 @@ class phpbb_template_twig implements phpbb_template  	}  	/** -	* Calls hook if any is defined. -	* -	* @param string $handle Template handle being displayed. -	* @param string $method Method name of the caller. -	*/ -	protected function call_hook($handle, $method) -	{ -		global $phpbb_hook; - -		if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, $method), $handle, $this)) -		{ -			if ($phpbb_hook->hook_return(array(__CLASS__, $method))) -			{ -				$result = $phpbb_hook->hook_return_result(array(__CLASS__, $method)); -				return array($result); -			} -		} - -		return false; -	} - -	/**  	* Display the handle and assign the output to a template variable  	* or return the compiled result.  	*  	* @param string $handle Handle to operate on  	* @param string $template_var Template variable to assign compiled handle to  	* @param bool $return_content If true return compiled handle, otherwise assign to $template_var -	* @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this +	* @return \phpbb\template\template|string if $return_content is true return string of the compiled handle, otherwise return $this  	*/  	public function assign_display($handle, $template_var = '', $return_content = true)  	{ @@ -326,111 +308,18 @@ class phpbb_template_twig implements phpbb_template  	}  	/** -	* Assign key variable pairs from an array -	* -	* @param array $vararray A hash of variable name => value pairs -	* @return phpbb_template $this -	*/ -	public function assign_vars(array $vararray) -	{ -		foreach ($vararray as $key => $val) -		{ -			$this->assign_var($key, $val); -		} - -		return $this; -	} - -	/** -	* Assign a single scalar value to a single key. -	* -	* Value can be a string, an integer or a boolean. -	* -	* @param string $varname Variable name -	* @param string $varval Value to assign to variable -	* @return phpbb_template $this -	*/ -	public function assign_var($varname, $varval) -	{ -		$this->context->assign_var($varname, $varval); - -		return $this; -	} - -	/** -	* Append text to the string value stored in a key. -	* -	* Text is appended using the string concatenation operator (.). -	* -	* @param string $varname Variable name -	* @param string $varval Value to append to variable -	* @return phpbb_template $this -	*/ -	public function append_var($varname, $varval) -	{ -		$this->context->append_var($varname, $varval); - -		return $this; -	} - -	/** -	* Assign key variable pairs from an array to a specified block -	* @param string $blockname Name of block to assign $vararray to -	* @param array $vararray A hash of variable name => value pairs -	* @return phpbb_template $this -	*/ -	public function assign_block_vars($blockname, array $vararray) -	{ -		$this->context->assign_block_vars($blockname, $vararray); - -		return $this; -	} - -	/** -	* Change already assigned key variable pair (one-dimensional - single loop entry) -	* -	* An example of how to use this function: -	* {@example alter_block_array.php} -	* -	* @param	string	$blockname	the blockname, for example 'loop' -	* @param	array	$vararray	the var array to insert/add or merge -	* @param	mixed	$key		Key to search for -	* -	* array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] -	* -	* int: Position [the position to change or insert at directly given] -	* -	* If key is false the position is set to 0 -	* If key is true the position is set to the last entry -	* -	* @param	string	$mode		Mode to execute (valid modes are 'insert' and 'change') -	* -	*	If insert, the vararray is inserted at the given position (position counting from zero). -	*	If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). -	* -	* Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) -	* and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) -	* -	* @return bool false on error, true on success -	*/ -	public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') -	{ -		return $this->context->alter_block_array($blockname, $vararray, $key, $mode); -	} - -	/**  	* Get template vars in a format Twig will use (from the context)  	*  	* @return array  	*/ -	public function get_template_vars() +	protected function get_template_vars()  	{  		$context_vars = $this->context->get_data_ref();  		$vars = array_merge(  			$context_vars['.'][0], // To get normal vars  			array( -				'definition'	=> new phpbb_template_twig_definition(), +				'definition'	=> new \phpbb\template\twig\definition(),  				'user'			=> $this->user,  				'loops'			=> $context_vars, // To get loops  			) @@ -443,17 +332,6 @@ class phpbb_template_twig implements phpbb_template  	}  	/** -	* Get a filename from the handle -	* -	* @param string $handle -	* @return string -	*/ -	protected function get_filename_from_handle($handle) -	{ -		return (isset($this->filenames[$handle])) ? $this->filenames[$handle] : $handle; -	} - -	/**  	* Get path to template for handle (required for BBCode parser)  	*  	* @return string | 
