Test Failed
Pull Request — master (#16)
by Divine Niiquaye
02:47
created

GroupingTrait   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 142
rs 10
wmc 25

7 Methods

Rating   Name   Duplication   Size   Complexity  
A generateRouteName() 0 13 4
A resolveWith() 0 17 6
A getRouteMaps() 0 3 1
A getDebugRoute() 0 3 1
A doMerge() 0 26 5
A processRouteMaps() 0 15 5
A loadAnnotation() 0 8 3
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[]|\ArrayIterator<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 DebugRoute|null */
48
    private $profiler;
49
50
    /** @var RouteCompilerInterface */
51
    private $compiler;
52
53
    public function getRouteMaps(): array
54
    {
55
        return [$this->staticRouteMap, $this->dynamicRoutesMap, $this->variableRouteData];
56
    }
57
58
    /**
59
     * If routes was debugged, return the profiler.
60
     */
61
    public function getDebugRoute(): ?DebugRoute
62
    {
63
        return $this->profiler;
64
    }
65
66
    /**
67
     * Load routes from annotation.
68
     */
69
    public function loadAnnotation(LoaderInterface $loader): void
70
    {
71
        $annotations = $loader->load();
72
73
        foreach ($annotations as $annotation) {
74
            if ($annotation instanceof self) {
75
                $this->hasGroups = true;
76
                $this->routes[] = $annotation;
77
            }
78
        }
79
    }
80
81
    /**
82
     * Bind route with collection.
83
     */
84
    private function resolveWith(Route $route): Route
85
    {
86
        if (null !== $stack = $this->stack) {
87
            foreach ($stack as $routeMethod => $arguments) {
88
                if (empty($arguments)) {
89
                    continue;
90
                }
91
92
                \call_user_func_array([$route, $routeMethod], 'prefix' === $routeMethod ? [\implode('', $arguments)] : $arguments);
93
            }
94
        }
95
96
        if (null !== $this->parent) {
97
            $route->end($this);
98
        }
99
100
        return $route;
101
    }
102
103
    /**
104
     * @return \ArrayIterator<int,Route>
105
     */
106
    private function doMerge(string $prefix, int $routeId, \ArrayIterator $routes): \ArrayIterator
107
    {
108
        $unnamedRoutes = [];
109
110
        /** @var Route|RouteCollection $route */
111
        foreach ($this->routes as $namePrefix => $route) {
112
            if ($route instanceof self) {
113
                $route->doMerge($prefix . (\is_string($namePrefix) ? $namePrefix : ''), $routeId, $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

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