diff options
Diffstat (limited to 'phpBB/phpbb/routing')
| -rw-r--r-- | phpBB/phpbb/routing/file_locator.php | 33 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/loader_resolver.php | 49 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/resources_locator/chained_resources_locator.php | 47 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/resources_locator/default_resources_locator.php | 105 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/resources_locator/resources_locator_interface.php | 27 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/router.php | 346 | 
6 files changed, 407 insertions, 200 deletions
| diff --git a/phpBB/phpbb/routing/file_locator.php b/phpBB/phpbb/routing/file_locator.php new file mode 100644 index 0000000000..64efcc6c76 --- /dev/null +++ b/phpBB/phpbb/routing/file_locator.php @@ -0,0 +1,33 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license       GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\routing; + +use phpbb\filesystem\filesystem_interface; +use Symfony\Component\Config\FileLocator; + +class file_locator extends FileLocator +{ +	public function __construct(filesystem_interface $filesystem, $paths = []) +	{ +		$paths = (array) $paths; +		$absolute_paths = []; + +		foreach ($paths as $path) +		{ +			$absolute_paths[] = $filesystem->realpath($path); +		} + +		parent::__construct($absolute_paths); +	} +} diff --git a/phpBB/phpbb/routing/loader_resolver.php b/phpBB/phpbb/routing/loader_resolver.php new file mode 100644 index 0000000000..e335051444 --- /dev/null +++ b/phpBB/phpbb/routing/loader_resolver.php @@ -0,0 +1,49 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license       GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\routing; + +use Symfony\Component\Config\Loader\LoaderResolverInterface; + +/** + * @see Symfony\Component\Config\Loader\LoaderResolver + */ +class loader_resolver implements LoaderResolverInterface +{ +	/** +	 * @var \Symfony\Component\Config\Loader\LoaderInterface[] An array of LoaderInterface objects +	 */ +	protected $loaders = []; + +	public function __construct($loaders = []) +	{ +		$this->loaders = $loaders; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function resolve($resource, $type = null) +	{ +		/** @var \Symfony\Component\Config\Loader\LoaderInterface $loader */ +		foreach ($this->loaders as $loader) +		{ +			if ($loader->supports($resource, $type)) +			{ +				return $loader; +			} +		} + +		return false; +	} +} diff --git a/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php b/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php new file mode 100644 index 0000000000..db9abf2095 --- /dev/null +++ b/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php @@ -0,0 +1,47 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license       GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\routing\resources_locator; + +class chained_resources_locator implements resources_locator_interface +{ +	/** +	 * @var resources_locator_interface[] +	 */ +	protected $locators; + +	/** +	 * Construct method +	 * +	 * @param resources_locator_interface[]	$locators	Locators +	 */ +	public function __construct($locators) +	{ +		$this->locators		= $locators; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function locate_resources() +	{ +		$resources = []; + +		foreach ($this->locators as $locator) +		{ +			$resources = array_merge($resources, $locator->locate_resources()); +		} + +		return $resources; +	} +} diff --git a/phpBB/phpbb/routing/resources_locator/default_resources_locator.php b/phpBB/phpbb/routing/resources_locator/default_resources_locator.php new file mode 100644 index 0000000000..90c3877007 --- /dev/null +++ b/phpBB/phpbb/routing/resources_locator/default_resources_locator.php @@ -0,0 +1,105 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license       GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\routing\resources_locator; + +use phpbb\extension\manager; + +/** + * Locates the yaml routing resources located in the default locations + */ +class default_resources_locator implements resources_locator_interface +{ +	/** +	 * phpBB root path +	 * +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Name of the current environment +	 * +	 * @var string +	 */ +	protected $environment; + +	/** +	 * Extension manager +	 * +	 * @var manager +	 */ +	protected $extension_manager; + +	/** +	 * Construct method +	 * +	 * @param string	$phpbb_root_path	phpBB root path +	 * @param string	$environment		Name of the current environment +	 * @param manager	$extension_manager	Extension manager +	 */ +	public function __construct($phpbb_root_path, $environment, manager $extension_manager = null) +	{ +		$this->phpbb_root_path		= $phpbb_root_path; +		$this->environment			= $environment; +		$this->extension_manager	= $extension_manager; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function locate_resources() +	{ +		$resources = [['config/' . $this->environment . '/routing/environment.yml', 'yaml']]; + +		$resources = $this->append_ext_resources($resources); + +		return $resources; +	} + +	/** +	 * Append extension resources to an array of resouces +	 * +	 * @see resources_locator_interface::locate_resources() +	 * +	 * @param mixed[] $resources List of resources +	 * +	 * @return mixed[] List of resources +	 */ +	protected function append_ext_resources(array $resources) +	{ +		if ($this->extension_manager !== null) +		{ +			foreach ($this->extension_manager->all_enabled(false) as $path) +			{ +				if (file_exists($this->phpbb_root_path . $path . 'config/' . $this->environment . '/routing/environment.yml')) +				{ +					$resources[] = [$path . 'config/' . $this->environment . '/routing/environment.yml', 'yaml']; +				} +				else if (!is_dir($this->phpbb_root_path . $path . 'config/' . $this->environment)) +				{ +					if (file_exists($this->phpbb_root_path . $path . 'config/default/routing/environment.yml')) +					{ +						$resources[] = [$path . 'config/default/routing/environment.yml', 'yaml']; +					} +					else if (!is_dir($this->phpbb_root_path . $path . 'config/default/routing') && file_exists($this->phpbb_root_path . $path . 'config/routing.yml')) +					{ +						$resources[] = [$path . 'config/routing.yml', 'yaml']; +					} +				} +			} +		} + +		return $resources; +	} +} diff --git a/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php b/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php new file mode 100644 index 0000000000..46335cb288 --- /dev/null +++ b/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php @@ -0,0 +1,27 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\routing\resources_locator; + +interface resources_locator_interface +{ +	/** +	 * Locates a list of resources used to load the routes +	 * +	 * Each entry of the list can be either the resource or an array composed of 2 elements: +	 * the resource and its type. +	 * +	 * @return mixed[] List of resources +	 */ +	public function locate_resources(); +} diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 5af005769f..5d237b6433 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -13,21 +13,20 @@  namespace phpbb\routing; +use phpbb\routing\resources_locator\resources_locator_interface;  use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Config\Loader\LoaderInterface;  use Symfony\Component\DependencyInjection\ContainerInterface;  use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;  use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Filesystem\Exception\IOException;  use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; -use Symfony\Component\Routing\Matcher\UrlMatcher;  use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Matcher\UrlMatcher;  use Symfony\Component\Routing\RequestContext;  use Symfony\Component\Routing\RouteCollection;  use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Routing\Loader\YamlFileLoader; -use Symfony\Component\Config\FileLocator; -use phpbb\extension\manager;  /**   * Integration of all pieces of the routing system for easier use. @@ -35,11 +34,19 @@ use phpbb\extension\manager;  class router implements RouterInterface  {  	/** -	 * Extension manager -	 * -	 * @var manager +	 * @var ContainerInterface  	 */ -	protected $extension_manager; +	protected $container; + +	/** +	 * @var resources_locator_interface +	 */ +	protected $resources_locator; + +	/** +	 * @var LoaderInterface +	 */ +	protected $loader;  	/**  	 * phpBB root path @@ -63,13 +70,6 @@ class router implements RouterInterface  	protected $environment;  	/** -	 * YAML file(s) containing route information -	 * -	 * @var array -	 */ -	protected $routing_files; - -	/**  	 * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null  	 */  	protected $matcher; @@ -85,37 +85,25 @@ class router implements RouterInterface  	protected $context;  	/** -	 * @var RouteCollection|null +	 * @var RouteCollection  	 */  	protected $route_collection;  	/** -	 * @var \phpbb\filesystem\filesystem_interface -	 */ -	protected $filesystem; - -	/** -	 * @var ContainerInterface -	 */ -	protected $container; - -	/**  	 * Construct method  	 * -	 * @param ContainerInterface	$container			DI container -	 * @param \phpbb\filesystem\filesystem_interface $filesystem	Filesystem helper -	 * @param string	$phpbb_root_path	phpBB root path -	 * @param string	$php_ext			PHP file extension -	 * @param string	$environment		Name of the current environment -	 * @param manager	$extension_manager	Extension manager -	 * @param array		$routing_files		Array of strings containing paths to YAML files holding route information +	 * @param ContainerInterface			$container			DI container +	 * @param resources_locator_interface	$resources_locator	Resources locator +	 * @param LoaderInterface				$loader				Resources loader +	 * @param string						$phpbb_root_path	phpBB root path +	 * @param string						$php_ext			PHP file extension +	 * @param string						$environment		Name of the current environment  	 */ -	public function __construct(ContainerInterface $container, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext, $environment, manager $extension_manager = null, $routing_files = array()) +	public function __construct(ContainerInterface $container, resources_locator_interface $resources_locator, LoaderInterface $loader, $phpbb_root_path, $php_ext, $environment)  	{  		$this->container			= $container; -		$this->filesystem			= $filesystem; -		$this->extension_manager	= $extension_manager; -		$this->routing_files		= $routing_files; +		$this->resources_locator	= $resources_locator; +		$this->loader				= $loader;  		$this->phpbb_root_path		= $phpbb_root_path;  		$this->php_ext				= $php_ext;  		$this->environment			= $environment; @@ -123,178 +111,28 @@ class router implements RouterInterface  	}  	/** -	 * Find the list of routing files +	 * Get the list of routes  	 * -	 * @param array $paths Array of paths where to look for routing files (they must be relative to the phpBB root path). -	 * @return router +	 * @return RouteCollection Get the route collection  	 */ -	public function find_routing_files(array $paths) +	public function get_routes()  	{ -		$this->routing_files = array('config/' . $this->environment . '/routing/environment.yml'); -		foreach ($paths as $path) +		if ($this->route_collection === null /*|| $this->route_collection->count() === 0*/)  		{ -			if (file_exists($this->phpbb_root_path . $path . 'config/' . $this->environment . '/routing/environment.yml')) -			{ -				$this->routing_files[] = $path . 'config/' . $this->environment . '/routing/environment.yml'; -			} -			else if (!is_dir($this->phpbb_root_path . $path . 'config/' . $this->environment)) +			$this->route_collection = new RouteCollection; +			foreach ($this->resources_locator->locate_resources() as $resource)  			{ -				if (file_exists($this->phpbb_root_path . $path . 'config/default/routing/environment.yml')) +				if (is_array($resource))  				{ -					$this->routing_files[] = $path . 'config/default/routing/environment.yml'; +					$this->route_collection->addCollection($this->loader->load($resource[0], $resource[1]));  				} -				else if (!is_dir($this->phpbb_root_path . $path . 'config/default/routing') && file_exists($this->phpbb_root_path . $path . 'config/routing.yml')) +				else  				{ -					$this->routing_files[] = $path . 'config/routing.yml'; +					$this->route_collection->addCollection($this->loader->load($resource));  				}  			} -		} -		return $this; -	} - -	/** -	 * Find a list of controllers -	 * -	 * @param string $base_path Base path to prepend to file paths -	 * @return router -	 */ -	public function find($base_path = '') -	{ -		if ($this->route_collection === null || $this->route_collection->count() === 0) -		{ -			$this->route_collection = new RouteCollection; -			foreach ($this->routing_files as $file_path) -			{ -				$loader = new YamlFileLoader(new FileLocator($this->filesystem->realpath($base_path))); -				$this->route_collection->addCollection($loader->load($file_path)); -			} -		} - -		$this->resolveParameters($this->route_collection); - -		return $this; -	} - -	/** -	 * Replaces placeholders with service container parameter values in: -	 * - the route defaults, -	 * - the route requirements, -	 * - the route path, -	 * - the route host, -	 * - the route schemes, -	 * - the route methods. -	 * -	 * @param RouteCollection $collection -	 */ -	private function resolveParameters(RouteCollection $collection) -	{ -		foreach ($collection as $route) -		{ -			foreach ($route->getDefaults() as $name => $value) -			{ -				$route->setDefault($name, $this->resolve($value)); -			} - -			$requirements = $route->getRequirements(); -			unset($requirements['_scheme']); -			unset($requirements['_method']); - -			foreach ($requirements as $name => $value) -			{ -				$route->setRequirement($name, $this->resolve($value)); -			} - -			$route->setPath($this->resolve($route->getPath())); -			$route->setHost($this->resolve($route->getHost())); - -			$schemes = array(); -			foreach ($route->getSchemes() as $scheme) -			{ -				$schemes = array_merge($schemes, explode('|', $this->resolve($scheme))); -			} - -			$route->setSchemes($schemes); -			$methods = array(); -			foreach ($route->getMethods() as $method) -			{ -				$methods = array_merge($methods, explode('|', $this->resolve($method))); -			} - -			$route->setMethods($methods); -			$route->setCondition($this->resolve($route->getCondition())); -		} -	} - -	/** -	 * Recursively replaces placeholders with the service container parameters. -	 * -	 * @param mixed $value The source which might contain "%placeholders%" -	 * -	 * @return mixed The source with the placeholders replaced by the container -	 *               parameters. Arrays are resolved recursively. -	 * -	 * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter -	 * @throws RuntimeException           When a container value is not a string or a numeric value -	 */ -	private function resolve($value) -	{ -		if (is_array($value)) -		{ -			foreach ($value as $key => $val) -			{ -				$value[$key] = $this->resolve($val); -			} - -			return $value; -		} - -		if (!is_string($value)) -		{ -			return $value; -		} - -		$container = $this->container; -		$escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container, $value) -		{ -			// skip %% -			if (!isset($match[1])) -			{ -				return '%%'; -			} - -			$resolved = $container->getParameter($match[1]); -			if (is_string($resolved) || is_numeric($resolved)) -			{ -				return (string) $resolved; -			} - -			throw new RuntimeException(sprintf( -					'The container parameter "%s", used in the route configuration value "%s", '. -					'must be a string or numeric, but it is of type %s.', -					$match[1], -					$value, -					gettype($resolved) -				) -			); -		}, $value); - -		return str_replace('%%', '%', $escapedValue); -	} - -	/** -	 * Get the list of routes -	 * -	 * @return RouteCollection Get the route collection -	 */ -	public function get_routes() -	{ -		if ($this->route_collection == null || empty($this->routing_files)) -		{ -			$this->find_routing_files( -					($this->extension_manager !== null) ? $this->extension_manager->all_enabled(false) : array() -				) -				->find($this->phpbb_root_path); +			$this->resolveParameters($this->route_collection);  		}  		return $this->route_collection; @@ -365,6 +203,7 @@ class router implements RouterInterface  		return $this->matcher;  	} +  	/**  	 * Creates a new dumped URL Matcher (dump it if necessary)  	 */ @@ -457,4 +296,111 @@ class router implements RouterInterface  	{  		$this->generator = new UrlGenerator($this->get_routes(), $this->context);  	} + +	/** +	 * Replaces placeholders with service container parameter values in: +	 * - the route defaults, +	 * - the route requirements, +	 * - the route path, +	 * - the route host, +	 * - the route schemes, +	 * - the route methods. +	 * +	 * @param RouteCollection $collection +	 */ +	protected function resolveParameters(RouteCollection $collection) +	{ +		/** @var \Symfony\Component\Routing\Route $route */ +		foreach ($collection as $route) +		{ +			foreach ($route->getDefaults() as $name => $value) +			{ +				$route->setDefault($name, $this->resolve($value)); +			} + +			$requirements = $route->getRequirements(); +			unset($requirements['_scheme']); +			unset($requirements['_method']); + +			foreach ($requirements as $name => $value) +			{ +				$route->setRequirement($name, $this->resolve($value)); +			} + +			$route->setPath($this->resolve($route->getPath())); +			$route->setHost($this->resolve($route->getHost())); + +			$schemes = array(); +			foreach ($route->getSchemes() as $scheme) +			{ +				$schemes = array_merge($schemes, explode('|', $this->resolve($scheme))); +			} + +			$route->setSchemes($schemes); +			$methods = array(); +			foreach ($route->getMethods() as $method) +			{ +				$methods = array_merge($methods, explode('|', $this->resolve($method))); +			} + +			$route->setMethods($methods); +			$route->setCondition($this->resolve($route->getCondition())); +		} +	} + +	/** +	 * Recursively replaces placeholders with the service container parameters. +	 * +	 * @param mixed $value The source which might contain "%placeholders%" +	 * +	 * @return mixed The source with the placeholders replaced by the container +	 *               parameters. Arrays are resolved recursively. +	 * +	 * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter +	 * @throws RuntimeException           When a container value is not a string or a numeric value +	 */ +	private function resolve($value) +	{ +		if (is_array($value)) +		{ +			foreach ($value as $key => $val) +			{ +				$value[$key] = $this->resolve($val); +			} + +			return $value; +		} + +		if (!is_string($value)) +		{ +			return $value; +		} + +		$container = $this->container; +		$escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container, $value) +		{ +			// skip %% +			if (!isset($match[1])) +			{ +				return '%%'; +			} + +			$resolved = $container->getParameter($match[1]); +			if (is_string($resolved) || is_numeric($resolved)) +			{ +				return (string) $resolved; +			} + +			throw new RuntimeException(sprintf( +					'The container parameter "%s", used in the route configuration value "%s", '. +					'must be a string or numeric, but it is of type %s.', +					$match[1], +					$value, +					gettype($resolved) +				) +			); +		}, $value); + +		return str_replace('%%', '%', $escapedValue); +	}  } | 
