RouterLayer   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 0
loc 125
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 18 7
A addRoute() 0 4 1
B in() 0 40 6
A generateUrl() 0 10 2
1
<?php
2
/**
3
 * Veto.
4
 * PHP Microframework.
5
 *
6
 * @author Damien Walsh <[email protected]>
7
 * @copyright Damien Walsh 2013-2014
8
 * @version 0.1
9
 * @package veto
10
 */
11
namespace Veto\Layer\Router;
12
13
use Veto\Collection\Bag;
14
use Veto\Layer\Router\Exception\RouterException;
15
use Veto\Configuration\Hive;
16
use Veto\DependencyInjection\AbstractContainerAccessor;
17
use Veto\Event\Dispatcher;
18
use Veto\Http\Request;
19
use Veto\Layer\InboundLayerInterface;
20
use Veto\Configuration\Exception\ConfigurationException;
21
22
/**
23
 * RouterLayer
24
 * Tags requests for the kernel to dispatch to controllers.
25
 *
26
 * @since 0.1
27
 */
28
class RouterLayer extends AbstractContainerAccessor implements InboundLayerInterface
29
{
30
    /**
31
     * The routes managed by this Router.
32
     *
33
     * @var \Veto\Collection\Bag
34
     */
35
    protected $routes;
36
37
    /**
38
     * The event dispatcher.
39
     *
40
     * @var \Veto\Event\Dispatcher
41
     */
42
    protected $dispatcher;
43
44
    /**
45
     * Initialise the router, optionally from configuration
46
     *
47
     * @param Hive $config
48
     * @param Dispatcher $dispatcher
49
     * @throws ConfigurationException
50
     */
51
    public function __construct(Hive $config = null, Dispatcher $dispatcher = null)
52
    {
53
        $this->routes = new Bag();
54
        $this->dispatcher = $dispatcher;
55
56
        if (!is_null($config) && isset($config['routes']) && is_array($config['routes'])) {
57
            foreach ($config['routes'] as $routeName => $route) {
58
                $this->addRoute(
59
                    $routeName,
60
                    $route['pattern'],
61
                    isset($route['rules']) ? $route['rules'] : array(),
62
                    isset($route['methods']) ? $route['methods'] : array(),
63
                    $route['controller'],
64
                    $route['action']
65
                );
66
            }
67
        }
68
    }
69
70
    /**
71
     * Add a route with an arbitrary method to the router.
72
     *
73
     * @param $name
74
     * @param $pattern
75
     * @param string[] $rules
76
     * @param string[] $methods
77
     * @param $controller
78
     * @param $action
79
     */
80
    public function addRoute($name, $pattern, array $rules, $methods = array('GET'), $controller, $action)
81
    {
82
        $this->routes->add($name, new Route($name, $pattern, $rules, $methods, $controller, $action));
83
    }
84
85
    /**
86
     * Tag a request $request with a controller so that the kernel (Veto\App)
87
     * can dispatch it to a controller.
88
     *
89
     * @param Request $request
90
     * @return Request
91
     * @throws \Exception
92
     */
93
    public function in(Request $request)
94
    {
95
        $tagged = false;
96
97
        /**
98
         * @var Route $route
99
         */
100
        foreach ($this->routes as $route) {
101
102
            $placeholders = $route->matches($request);
103
            if ($placeholders !== false) {
104
105
                // Dispatch a matched event
106
                if (!is_null($this->dispatcher)) {
107
                    $this->dispatcher->dispatch(RouterEvent::ROUTE_MATCHED, new RouterEvent($route, $this));
108
                }
109
110
                // Add the matched route's parameters to the request
111
                $request = $request->withParameter('_controller', array(
112
                    'class' => $route->getController(),
113
                    'method' => $route->getAction()
114
                ));
115
116
                // Add any matched route placeholders to the request parameters
117
                foreach ($placeholders as $placeholderKey => $placeholderValue) {
118
                    $request = $request->withParameter($placeholderKey, $placeholderValue);
119
                }
120
121
                $tagged = true;
122
                break;
123
            }
124
        }
125
126
        // If no suitable route was found...
127
        if (!$tagged) {
128
            throw RouterException::noRouteExists($request->getMethod(), $request->getUri()->getPath());
129
        }
130
131
        return $request;
132
    }
133
134
    /**
135
     * Generate a URL from a route name and paramters.
136
     *
137
     * @param string $routeName
138
     * @param array $parameters
139
     * @return string
140
     * @throws \Exception
141
     */
142
    public function generateUrl($routeName, array $parameters = array())
143
    {
144
        $route = $this->routes->get($routeName);
145
146
        if (!($route instanceof Route)) {
147
            throw RouterException::nonExistentRoute($routeName);
148
        }
149
150
        return $route->generateUrl($parameters);
151
    }
152
}
153