aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb/routing/router.php
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb/routing/router.php')
-rw-r--r--phpBB/phpbb/routing/router.php235
1 files changed, 149 insertions, 86 deletions
diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php
index 2f89d4e884..5d237b6433 100644
--- a/phpBB/phpbb/routing/router.php
+++ b/phpBB/phpbb/routing/router.php
@@ -13,18 +13,20 @@
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\Matcher\Dumper\PhpMatcherDumper;
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.
@@ -32,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
@@ -60,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;
@@ -82,31 +85,25 @@ class router implements RouterInterface
protected $context;
/**
- * @var RouteCollection|null
+ * @var RouteCollection
*/
protected $route_collection;
/**
- * @var \phpbb\filesystem\filesystem_interface
- */
- protected $filesystem;
-
- /**
* Construct method
*
- * @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|null $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(\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->filesystem = $filesystem;
- $this->extension_manager = $extension_manager;
- $this->routing_files = $routing_files;
+ $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;
@@ -114,70 +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));
- }
- }
-
- return $this;
- }
-
- /**
- * 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;
@@ -248,6 +203,7 @@ class router implements RouterInterface
return $this->matcher;
}
+
/**
* Creates a new dumped URL Matcher (dump it if necessary)
*/
@@ -340,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);
+ }
}