Mark V
1: <?php
2: namespace MOC\V\Component\Router\Component\Bridge\Repository;
3:
4: use MOC\V\Component\Router\Component\Bridge\Bridge;
5: use MOC\V\Component\Router\Component\Exception\ComponentException;
6: use MOC\V\Component\Router\Component\Exception\Repository\MissingParameterException;
7: use MOC\V\Component\Router\Component\IBridgeInterface;
8: use MOC\V\Component\Router\Component\Parameter\Repository\RouteParameter;
9: use MOC\V\Core\HttpKernel\HttpKernel;
10:
11: /**
12: * Class UniversalRouter
13: *
14: * @package MOC\V\Component\Router\Component\Bridge
15: */
16: class UniversalRouter extends Bridge implements IBridgeInterface
17: {
18:
19: private $RouteCollection = array();
20:
21: /**
22: * @param RouteParameter $RouteOption
23: *
24: * @return IBridgeInterface
25: */
26: public function addRoute(RouteParameter $RouteOption)
27: {
28:
29: $this->RouteCollection[$RouteOption->getPath()] = $RouteOption;
30: return $this;
31: }
32:
33: /**
34: * @param null|string $Path
35: *
36: * @return string
37: * @throws ComponentException
38: */
39: public function getRoute($Path = null)
40: {
41:
42: if (null === $Path) {
43: /** @var RouteParameter $Route */
44: $Route = $this->RouteCollection[HttpKernel::getRequest()->getPathInfo()];
45: } else {
46: /** @var RouteParameter $Route */
47: // @codeCoverageIgnoreStart
48: $Route = $this->RouteCollection[$Path];
49: // @codeCoverageIgnoreEnd
50: }
51: $Controller = $this->handleController($Route);
52: if (!is_callable($Controller)) {
53: // @codeCoverageIgnoreStart
54: throw new ComponentException($Controller);
55: // @codeCoverageIgnoreEnd
56: }
57: $Arguments = $this->handleArguments($Controller, $Route);
58: $Response = call_user_func_array($Controller, $Arguments);
59: return $Response;
60: }
61:
62: /**
63: * @param RouteParameter $Route
64: *
65: * @throws ComponentException
66: * @return callable
67: */
68: private function handleController(RouteParameter $Route)
69: {
70:
71: $Class = $Route->getClass();
72: if (!class_exists($Class, true)) {
73: // @codeCoverageIgnoreStart
74: throw new ComponentException($Class);
75: // @codeCoverageIgnoreEnd
76: }
77: $Method = $Route->getMethod();
78:
79: $Object = new $Class();
80: if (!method_exists($Object, $Method)) {
81: // @codeCoverageIgnoreStart
82: throw new ComponentException($Method);
83: // @codeCoverageIgnoreEnd
84: }
85:
86: return array($Object, $Method);
87: }
88:
89: /**
90: * @param callable $Controller
91: * @param RouteParameter $Route
92: *
93: * @throws MissingParameterException
94: * @return array
95: */
96: private function handleArguments($Controller, RouteParameter $Route)
97: {
98:
99: $Reflection = new \ReflectionMethod($Controller[0], $Controller[1]);
100: $MethodParameters = $Reflection->getParameters();
101: $RequestParameters = HttpKernel::getRequest()->getParameterArray();
102: $MethodArguments = array();
103: /** @var \ReflectionParameter $MethodParameter */
104: foreach ((array)$MethodParameters as $MethodParameter) {
105: // @codeCoverageIgnoreStart
106: if (array_key_exists($MethodParameter->name, $RequestParameters)) {
107: $MethodArguments[] = $RequestParameters[$MethodParameter->name];
108: } elseif (array_key_exists($MethodParameter->name, $Route->getParameterDefault())) {
109: $MethodArguments[] = $Route->getParameterDefault($MethodParameter->name);
110: } elseif ($MethodParameter->isDefaultValueAvailable()) {
111: $MethodArguments[] = $MethodParameter->getDefaultValue();
112: } else {
113: throw new MissingParameterException($MethodParameter->name);
114: }
115: // @codeCoverageIgnoreEnd
116: }
117: return $MethodArguments;
118: }
119:
120: /**
121: * @return array
122: *
123: * @codeCoverageIgnore
124: */
125: public function getRouteList()
126: {
127:
128: return array_keys($this->RouteCollection);
129: }
130: }
131: