diff options
Diffstat (limited to 'phpBB/phpbb/routing')
| -rw-r--r-- | phpBB/phpbb/routing/file_locator.php | 33 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/helper.php | 153 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/loader_resolver.php | 50 | ||||
| -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/installer_resources_locator.php | 78 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/resources_locator/resources_locator_interface.php | 27 | ||||
| -rw-r--r-- | phpBB/phpbb/routing/router.php | 406 | 
8 files changed, 899 insertions, 0 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/helper.php b/phpBB/phpbb/routing/helper.php new file mode 100644 index 0000000000..f56974a354 --- /dev/null +++ b/phpBB/phpbb/routing/helper.php @@ -0,0 +1,153 @@ +<?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\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RequestContext; + +/** +* Controller helper class, contains methods that do things for controllers +*/ +class helper +{ +	/** +	 * config object +	 * @var \phpbb\config\config +	 */ +	protected $config; + +	/** +	 * phpBB router +	 * @var \phpbb\routing\router +	 */ +	protected $router; + +	/** +	 * @var \phpbb\symfony_request +	 */ +	protected $symfony_request; + +	/** +	 * @var \phpbb\request\request_interface +	 */ +	protected $request; + +	/** +	 * @var \phpbb\filesystem The filesystem object +	 */ +	protected $filesystem; + +	/** +	 * phpBB root path +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * PHP file extension +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\config\config $config Config object +	 * @param \phpbb\routing\router $router phpBB router +	 * @param \phpbb\symfony_request $symfony_request Symfony Request object +	 * @param \phpbb\request\request_interface $request phpBB request object +	 * @param \phpbb\filesystem\filesystem $filesystem The filesystem object +	 * @param string $phpbb_root_path phpBB root path +	 * @param string $php_ext PHP file extension +	 */ +	public function __construct(\phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem $filesystem, $phpbb_root_path, $php_ext) +	{ +		$this->config = $config; +		$this->router = $router; +		$this->symfony_request = $symfony_request; +		$this->request = $request; +		$this->filesystem = $filesystem; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $php_ext; +	} + +	/** +	 * Generate a URL to a route +	 * +	 * @param string	$route		Name of the route to travel +	 * @param array	$params		String or array of additional url parameters +	 * @param bool	$is_amp		Is url using & (true) or & (false) +	 * @param string|bool		$session_id	Possibility to use a custom session id instead of the global one +	 * @param bool|string		$reference_type The type of reference to be generated (one of the constants) +	 * @return string The URL already passed through append_sid() +	 */ +	public function route($route, array $params = array(), $is_amp = true, $session_id = false, $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH) +	{ +		$anchor = ''; +		if (isset($params['#'])) +		{ +			$anchor = '#' . $params['#']; +			unset($params['#']); +		} + +		$context = new RequestContext(); +		$context->fromRequest($this->symfony_request); + +		$script_name = $this->symfony_request->getScriptName(); +		$page_name = substr($script_name, -1, 1) == '/' ? '' : utf8_basename($script_name); + +		$base_url = $context->getBaseUrl(); + +		// Append page name if base URL does not contain it +		if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false) +		{ +			$base_url .= '/' . $page_name; +		} + +		// If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it. +		$base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url); + +		// We need to update the base url to move to the directory of the app.php file if the current script is not app.php +		if ($page_name !== 'app.php') +		{ +			if (empty($this->config['enable_mod_rewrite'])) +			{ +				$base_url = str_replace('/app.' . $this->php_ext, '/' . $this->phpbb_root_path . 'app.' . $this->php_ext, $base_url); +			} +			else +			{ +				$base_url .= preg_replace(get_preg_expression('path_remove_dot_trailing_slash'), '$2', $this->phpbb_root_path); +			} +		} + +		$base_url = $this->request->escape($this->filesystem->clean_path($base_url), true); + +		$context->setBaseUrl($base_url); + +		$this->router->setContext($context); +		$route_url = $this->router->generate($route, $params, $reference_type); + +		if ($is_amp) +		{ +			$route_url = str_replace(array('&', '&'), array('&', '&'), $route_url); +		} + +		if ($reference_type === UrlGeneratorInterface::RELATIVE_PATH && empty($this->config['enable_mod_rewrite'])) +		{ +			$route_url = 'app.' . $this->php_ext . '/' . $route_url; +		} + +		return append_sid($route_url . $anchor, false, $is_amp, $session_id, true); +	} +} diff --git a/phpBB/phpbb/routing/loader_resolver.php b/phpBB/phpbb/routing/loader_resolver.php new file mode 100644 index 0000000000..13fbc6405c --- /dev/null +++ b/phpBB/phpbb/routing/loader_resolver.php @@ -0,0 +1,50 @@ +<?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)) +			{ +				$loader->setResolver($this); +				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/installer_resources_locator.php b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php new file mode 100644 index 0000000000..42cd0f11af --- /dev/null +++ b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php @@ -0,0 +1,78 @@ +<?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\filesystem\filesystem_interface; + +/** + * Locates the yaml routing resources taking update directories into consideration + */ +class installer_resources_locator implements resources_locator_interface +{ +	/** +	 * phpBB's filesystem handler +	 * +	 * @var filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * phpBB root path +	 * +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Name of the current environment +	 * +	 * @var string +	 */ +	protected $environment; + +	/** +	 * Construct method +	 * +	 * @param filesystem_interface	$filesystem			phpBB's filesystem handler +	 * @param string				$phpbb_root_path	phpBB root path +	 * @param string				$environment		Name of the current environment +	 */ +	public function __construct(filesystem_interface $filesystem, $phpbb_root_path, $environment) +	{ +		$this->filesystem			= $filesystem; +		$this->phpbb_root_path		= $phpbb_root_path; +		$this->environment			= $environment; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function locate_resources() +	{ +		if ($this->filesystem->exists($this->phpbb_root_path . 'install/update/new/config')) +		{ +			$resources = array( +				array('install/update/new/config/' . $this->environment . '/routing/environment.yml', 'yaml') +			); +		} +		else +		{ +			$resources = array( +				array('config/' . $this->environment . '/routing/environment.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 new file mode 100644 index 0000000000..5d237b6433 --- /dev/null +++ b/phpBB/phpbb/routing/router.php @@ -0,0 +1,406 @@ +<?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\routing\resources_locator\resources_locator_interface; +use Symfony\Component\Config\ConfigCache; +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\Filesystem\Exception\IOException; +use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; +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; + +/** + * Integration of all pieces of the routing system for easier use. + */ +class router implements RouterInterface +{ +	/** +	 * @var ContainerInterface +	 */ +	protected $container; + +	/** +	 * @var resources_locator_interface +	 */ +	protected $resources_locator; + +	/** +	 * @var LoaderInterface +	 */ +	protected $loader; + +	/** +	 * phpBB root path +	 * +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * PHP file extensions +	 * +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * Name of the current environment +	 * +	 * @var string +	 */ +	protected $environment; + +	/** +	 * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null +	 */ +	protected $matcher; + +	/** +	 * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface|null +	 */ +	protected $generator; + +	/** +	 * @var RequestContext +	 */ +	protected $context; + +	/** +	 * @var RouteCollection +	 */ +	protected $route_collection; + +	/** +	 * Construct method +	 * +	 * @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, resources_locator_interface $resources_locator, LoaderInterface $loader, $phpbb_root_path, $php_ext, $environment) +	{ +		$this->container			= $container; +		$this->resources_locator	= $resources_locator; +		$this->loader				= $loader; +		$this->phpbb_root_path		= $phpbb_root_path; +		$this->php_ext				= $php_ext; +		$this->environment			= $environment; +		$this->context				= new RequestContext(); +	} + +	/** +	 * Get the list of routes +	 * +	 * @return RouteCollection Get the route collection +	 */ +	public function get_routes() +	{ +		if ($this->route_collection === null /*|| $this->route_collection->count() === 0*/) +		{ +			$this->route_collection = new RouteCollection; +			foreach ($this->resources_locator->locate_resources() as $resource) +			{ +				if (is_array($resource)) +				{ +					$this->route_collection->addCollection($this->loader->load($resource[0], $resource[1])); +				} +				else +				{ +					$this->route_collection->addCollection($this->loader->load($resource)); +				} +			} + +			$this->resolveParameters($this->route_collection); +		} + +		return $this->route_collection; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function getRouteCollection() +	{ +		return $this->get_routes(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function setContext(RequestContext $context) +	{ +		$this->context = $context; + +		if ($this->matcher !== null) +		{ +			$this->get_matcher()->setContext($context); +		} +		if ($this->generator !== null) +		{ +			$this->get_generator()->setContext($context); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function getContext() +	{ +		return $this->context; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) +	{ +		return $this->get_generator()->generate($name, $parameters, $referenceType); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function match($pathinfo) +	{ +		return $this->get_matcher()->match($pathinfo); +	} + +	/** +	 * Gets the UrlMatcher instance associated with this Router. +	 * +	 * @return \Symfony\Component\Routing\Matcher\UrlMatcherInterface A UrlMatcherInterface instance +	 */ +	public function get_matcher() +	{ +		if ($this->matcher !== null) +		{ +			return $this->matcher; +		} + +		$this->create_dumped_url_matcher(); + +		return $this->matcher; +	} + +	/** +	 * Creates a new dumped URL Matcher (dump it if necessary) +	 */ +	protected function create_dumped_url_matcher() +	{ +		try +		{ +			$cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_matcher.{$this->php_ext}", defined('DEBUG')); +			if (!$cache->isFresh()) +			{ +				$dumper = new PhpMatcherDumper($this->get_routes()); + +				$options = array( +					'class'      => 'phpbb_url_matcher', +					'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', +				); + +				$cache->write($dumper->dump($options), $this->get_routes()->getResources()); +			} + +			require_once($cache->getPath()); + +			$this->matcher = new \phpbb_url_matcher($this->context); +		} +		catch (IOException $e) +		{ +			$this->create_new_url_matcher(); +		} +	} + +	/** +	 * Creates a new URL Matcher +	 */ +	protected function create_new_url_matcher() +	{ +		$this->matcher = new UrlMatcher($this->get_routes(), $this->context); +	} + +	/** +	 * Gets the UrlGenerator instance associated with this Router. +	 * +	 * @return \Symfony\Component\Routing\Generator\UrlGeneratorInterface A UrlGeneratorInterface instance +	 */ +	public function get_generator() +	{ +		if ($this->generator !== null) +		{ +			return $this->generator; +		} + +		$this->create_dumped_url_generator(); + +		return $this->generator; +	} + +	/** +	 * Creates a new dumped URL Generator (dump it if necessary) +	 */ +	protected function create_dumped_url_generator() +	{ +		try +		{ +			$cache = new ConfigCache("{$this->phpbb_root_path}cache/{$this->environment}/url_generator.{$this->php_ext}", defined('DEBUG')); +			if (!$cache->isFresh()) +			{ +				$dumper = new PhpGeneratorDumper($this->get_routes()); + +				$options = array( +					'class'      => 'phpbb_url_generator', +					'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', +				); + +				$cache->write($dumper->dump($options), $this->get_routes()->getResources()); +			} + +			require_once($cache->getPath()); + +			$this->generator = new \phpbb_url_generator($this->context); +		} +		catch (IOException $e) +		{ +			$this->create_new_url_generator(); +		} +	} + +	/** +	 * Creates a new URL Generator +	 */ +	protected function create_new_url_generator() +	{ +		$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); +	} +} | 
