Test Failed
Pull Request — master (#16)
by Divine Niiquaye
03:04
created

GroupingTrait::getRouteMaps()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.1 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Flight\Routing\Traits;
19
20
use Biurad\Annotations\LoaderInterface;
21
use Flight\Routing\{CompiledRoute, DebugRoute, Route};
22
use Flight\Routing\Interfaces\RouteCompilerInterface;
23
24
trait GroupingTrait
25
{
26
    /** @var array<string,array<string,mixed>> */
27
    private $staticRouteMap = [];
28
29
    /** @var array<int,array> */
30
    private $variableRouteData = [];
31
32
    /** @var string[] */
33
    protected $dynamicRoutesMap = [];
34
35
    /** @var Route[]|\SplFixedArray<int,Route> */
36
    private $routes = [];
37
38
    /** @var bool */
39
    private $hasGroups = false;
40
41
    /** @var self|null */
42
    private $parent = null;
43
44
    /** @var array<string,mixed[]>|null */
45
    private $stack = null;
46
47
    /** @var int */
48
    private $countRoutes = 0;
49
50
    /** @var DebugRoute|null */
51
    private $profiler;
52
53
    /** @var RouteCompilerInterface */
54
    private $compiler;
55
56
    public function getRouteMaps(): array
57
    {
58
        return [$this->staticRouteMap, $this->dynamicRoutesMap, $this->variableRouteData];
59
    }
60
61
    /**
62
     * If routes was debugged, return the profiler.
63
     */
64
    public function getDebugRoute(): ?DebugRoute
65
    {
66
        return $this->profiler;
67
    }
68
69
    /**
70
     * Load routes from annotation.
71
     */
72
    public function loadAnnotation(LoaderInterface $loader): void
73
    {
74
        $annotations = $loader->load();
75
76
        foreach ($annotations as $annotation) {
77
            if ($annotation instanceof self) {
78
                $this->hasGroups = true;
79
                $this->routes[] = $annotation;
80
            }
81
        }
82
    }
83
84
    /**
85
     * Bind route with collection.
86
     */
87
    private function resolveWith(Route $route): Route
88
    {
89
        if (null !== $stack = $this->stack) {
90
            foreach ($stack as $routeMethod => $arguments) {
91
                if (empty($arguments)) {
92
                    continue;
93
                }
94
95
                \call_user_func_array([$route, $routeMethod], 'prefix' === $routeMethod ? [\implode('', $arguments)] : $arguments);
96
            }
97
        }
98
99
        if (null !== $this->parent) {
100
            $route->end($this);
101
        }
102
103
        ++$this->countRoutes;
104
105
        return $route;
106
    }
107
108
    /**
109
     * @return \SplFixedArray<int,Route>
110
     */
111
    private function doMerge(string $prefix, self $routes): \SplFixedArray
112
    {
113
        $unnamedRoutes = [];
114
115
        /** @var Route|RouteCollection $route */
116
        foreach ($this->routes as $namePrefix => $route) {
117
            if ($route instanceof self) {
118
                $route->doMerge($prefix . (\is_string($namePrefix) ? $namePrefix : ''), $routes);
0 ignored issues
show
Bug introduced by
The method doMerge() does not exist on Flight\Routing\Route. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

118
                $route->/** @scrutinizer ignore-call */ 
119
                        doMerge($prefix . (\is_string($namePrefix) ? $namePrefix : ''), $routes);
Loading history...
119
120
                continue;
121
            }
122
123
            $routes->routes[] = $route->bind($name = $prefix . $this->generateRouteName($route, $unnamedRoutes));
124
125
            if (null !== $this->profiler) {
126
                $routes->profiler->addProfile($name, $route);
127
            }
128
129
            $this->processRouteMaps($route, $routes->compiler->compile($route), $routes);
130
        }
131
132
        [$this->hasGroups, $this->staticRouteMap, $this->dynamicRoutesMap, $this->variableRouteData, $this->profiler] = [$routes->hasGroups, $routes->staticRouteMap, $routes->dynamicRoutesMap, $routes->variableRouteData, $routes->profiler];
133
134
        return \SplFixedArray::fromArray($routes->routes);
135
    }
136
137
    private function processRouteMaps(Route $route, CompiledRoute $compiledRoute, self $routes): void
138
    {
139
        $routeId = $routes->countRoutes;
140
        $methods = \array_unique($route->get('methods'));
141
142
        $hostsRegex = $compiledRoute->getHostsRegex();
143
        $routes->variableRouteData[$routeId] = $compiledRoute->getVariables();
144
145
        $pathRegex = $compiledRoute->getPathRegex();
146
147
        if (0 === \strpos($pathRegex, '\\/')) {
148
            $methodsRegex = '(?|' . \implode('|', $methods) .'|([A-Z]+))';
149
            $hostsRegex = empty($hostsRegex) ? '?(?:\\/{2}[^\/]+)?' : '\\/{2}(?i:' . \implode('|', $hostsRegex) . ')';
150
            $regex = \preg_replace('/\?(?|P<\w+>|<\w+>|\'\w+\')/', '', $methodsRegex . $hostsRegex . $pathRegex);
151
152
            $routes->dynamicRoutesMap[] = $regex . '(*:' . $routeId . ')';
153
        } else {
154
            foreach ($methods as $method) {
155
                $routes->staticRouteMap[$pathRegex][$method] = [!empty($hostsRegex) ? '#^(?|' . \implode('|', $hostsRegex) . ')$#i' : null, $routeId];
156
            }
157
        }
158
159
        ++$routes->countRoutes;
160
    }
161
162
    private function generateRouteName(Route $route, array $unnamedRoutes): string
163
    {
164
        if (null === $name = $route->get('name')) {
165
            $name = $route->generateRouteName('');
166
167
            if (isset($unnamedRoutes[$name])) {
168
                $name .= ('_' !== $name[-1] ? '_' : '') . ++$unnamedRoutes[$name];
169
            } else {
170
                $unnamedRoutes[$name] = 0;
171
            }
172
        }
173
174
        return $name;
175
    }
176
}
177