Completed
Push — master ( 35c1c3...0dd52b )
by Dawid
10s
created

Router::findRoute()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 2
dl 0
loc 15
ccs 10
cts 10
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Igni\Http\Router;
4
5
use Igni\Http\Exception\GenericHttpException;;
6
use Igni\Http\Route;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Igni\Http\Router\Route. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Igni\Http\Router as RouterInterface;
8
use Symfony\Component\Routing\Route as SymfonyRoute;
9
use Symfony\Component\Routing\Exception\MethodNotAllowedException as SymfonyMethodNotAllowedException;
10
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
11
use Symfony\Component\Routing\Matcher\UrlMatcher;
12
use Symfony\Component\Routing\RequestContext;
13
use Symfony\Component\Routing\RouteCollection;
14
15
/**
16
 * Wrapper for package symfony/router
17
 *
18
 * @package Igni\Http\Router
19
 */
20
class Router implements RouterInterface
21
{
22
    /** @var RouteCollection */
23
    protected $routeCollection;
24
25
    /** @var Route[] */
26
    protected $routes = [];
27
28 19
    public function __construct()
29
    {
30 19
        $this->routeCollection = new RouteCollection();
31 19
    }
32
33
    /**
34
     * Registers new route.
35
     *
36
     * @param \Igni\Http\Router\Route $route
37
     */
38 14
    public function addRoute(Route $route): void
39
    {
40 14
        $name = $route->getName();
0 ignored issues
show
Bug introduced by
The method getName() does not exist on Igni\Http\Route. Since it exists in all sub-types, consider adding an abstract or default implementation to Igni\Http\Route. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

40
        /** @scrutinizer ignore-call */ 
41
        $name = $route->getName();
Loading history...
41
42 14
        $baseRoute = new SymfonyRoute($route->getPath());
43 14
        $baseRoute->setMethods($route->getMethods());
44
45 14
        $this->routeCollection->add($name, $baseRoute);
46 14
        $this->routes[$name] = $route;
47 14
    }
48
49
    /**
50
     * Finds route matching clients request.
51
     *
52
     * @param string $method request method.
53
     * @param string $path request path.
54
     * @return Route
55
     */
56 15
    public function findRoute(string $method, string $path): Route
57
    {
58 15
        $matcher = new UrlMatcher($this->routeCollection, new RequestContext('/', $method));
59
        try {
60 15
            $route = $matcher->match($path);
61 4
        } catch (ResourceNotFoundException $exception) {
62 3
            throw GenericHttpException::invalidUri($path, $method);
63 1
        } catch (SymfonyMethodNotAllowedException $exception) {
64 1
            throw GenericHttpException::methodNotAllowed($path, $method, $exception->getAllowedMethods());
65
        }
66
67 11
        $routeName = $route['_route'];
68 11
        unset($route['_route']);
69
70 11
        return $this->routes[$routeName]->withAttributes($route);
71
    }
72
}
73