Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
20.00% |
3 / 15 |
CRAP | |
53.12% |
51 / 96 |
router | |
0.00% |
0 / 1 |
|
20.00% |
3 / 15 |
178.00 | |
53.12% |
51 / 96 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
7 / 7 |
|||
get_routes | |
0.00% |
0 / 1 |
4.03 | |
87.50% |
7 / 8 |
|||
getRouteCollection | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
setContext | |
0.00% |
0 / 1 |
3.04 | |
83.33% |
5 / 6 |
|||
getContext | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
generate | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
match | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
get_matcher | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 4 |
|||
create_dumped_url_matcher | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 10 |
|||
create_new_url_matcher | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 2 |
|||
get_generator | |
0.00% |
0 / 1 |
2.50 | |
50.00% |
2 / 4 |
|||
create_dumped_url_generator | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 10 |
|||
create_new_url_generator | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
resolveParameters | |
0.00% |
0 / 1 |
6.12 | |
85.00% |
17 / 20 |
|||
resolve | |
0.00% |
0 / 1 |
12.21 | |
52.63% |
10 / 19 |
<?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; | |
/** | |
* PHP file extensions | |
* | |
* @var string | |
*/ | |
protected $php_ext; | |
/** | |
* @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; | |
/** | |
* @var string | |
*/ | |
protected $cache_dir; | |
/** | |
* Construct method | |
* | |
* @param ContainerInterface $container DI container | |
* @param resources_locator_interface $resources_locator Resources locator | |
* @param LoaderInterface $loader Resources loader | |
* @param string $php_ext PHP file extension | |
* @param string $cache_dir phpBB cache directory | |
*/ | |
public function __construct(ContainerInterface $container, resources_locator_interface $resources_locator, LoaderInterface $loader, $php_ext, $cache_dir) | |
{ | |
$this->container = $container; | |
$this->resources_locator = $resources_locator; | |
$this->loader = $loader; | |
$this->php_ext = $php_ext; | |
$this->context = new RequestContext(); | |
$this->cache_dir = $cache_dir; | |
} | |
/** | |
* 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->cache_dir}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->cache_dir}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); | |
} | |
} |