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

GroupingTrait::processRouteMaps()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 4
b 0
f 0
nc 3
nop 3
dl 0
loc 9
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\{DebugRoute, Route};
22
use Flight\Routing\Interfaces\RouteCompilerInterface;
23
24
trait GroupingTrait
25
{
26
    /** @var array */
27
    private $cacheData = null;
28
29
    /** @var self|null */
30
    private $parent = null;
31
32
    /** @var array<string,mixed[]>|null */
33
    private $stack = null;
34
35
    /** @var int */
36
    private $countRoutes = 0;
37
38
    /** @var DebugRoute|null */
39
    private $profiler = null;
40
41
    /** @var RouteCompilerInterface */
42
    private $compiler;
43
44
    /**
45
     * If routes was debugged, return the profiler.
46
     */
47
    public function getDebugRoute(): ?DebugRoute
48
    {
49
        return $this->profiler;
50
    }
51
52
    /**
53
     * Load routes from annotation.
54
     */
55
    public function loadAnnotation(LoaderInterface $loader): void
56
    {
57
        $annotations = $loader->load();
58
59
        foreach ($annotations as $annotation) {
60
            if ($annotation instanceof self) {
61
                $this['group'][] = $annotation;
62
            }
63
        }
64
    }
65
66
    /**
67
     * Bind route with collection.
68
     */
69
    private function resolveWith(Route $route): Route
70
    {
71
        if (null !== $stack = $this->stack) {
72
            foreach ($stack as $routeMethod => $arguments) {
73
                if (empty($arguments)) {
74
                    continue;
75
                }
76
77
                \call_user_func_array([$route, $routeMethod], 'prefix' === $routeMethod ? [\implode('', $arguments)] : $arguments);
78
            }
79
        }
80
81
        if (null === $this->parent) {
82
            $this->processRouteMaps($route, $this->countRoutes, $this);
0 ignored issues
show
Bug introduced by
$this of type Flight\Routing\Traits\GroupingTrait is incompatible with the type ArrayIterator expected by parameter $routes of Flight\Routing\Traits\Gr...ait::processRouteMaps(). ( Ignorable by Annotation )

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

82
            $this->processRouteMaps($route, $this->countRoutes, /** @scrutinizer ignore-type */ $this);
Loading history...
83
84
            if (null !== $this->profiler) {
85
                $this->profiler->addProfile($route);
86
            }
87
        } else {
88
            $route->belong($this); // Attach grouping to route.
89
        }
90
91
        ++$this->countRoutes;
92
93
        return $route;
94
    }
95
96
    /**
97
     * @param \ArrayIterator<string,mixed> $routes
98
     *
99
     * @return array<int,Route>
100
     */
101
    private function doMerge(string $prefix, self $routes, bool $merge = true): void
102
    {
103
        $unnamedRoutes = [];
104
105
        foreach ($this->offsetGet('group') as $namePrefix => $group) {
0 ignored issues
show
Bug introduced by
It seems like offsetGet() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

105
        foreach ($this->/** @scrutinizer ignore-call */ offsetGet('group') as $namePrefix => $group) {
Loading history...
106
            $prefix .= \is_string($namePrefix) ? $namePrefix : '';
107
108
            foreach ($group['routes'] ?? [] as $route) {
109
                $routes['routes'][] = $route->bind($this->generateRouteName($route, $prefix, $unnamedRoutes));
110
111
                if (null !== $routes->profiler) {
112
                    $routes->profiler->addProfile($route);
113
                }
114
115
                $this->processRouteMaps($route, $routes->countRoutes, $routes);
116
117
                ++$routes->countRoutes;
118
            }
119
120
            if ($group->offsetExists('group')) {
121
                $group->doMerge($prefix, $routes, false);
122
            }
123
        }
124
125
        if ($merge) {
126
            $routes->offsetUnset('group'); // Unset grouping ...
127
        }
128
    }
129
130
    /**
131
     * @param \ArrayIterator|array $routes
132
     */
133
    private function processRouteMaps(Route $route, int $routeId, \ArrayIterator $routes): void
134
    {
135
        [$pathRegex, $hostsRegex, $variables] = $this->compiler->compile($route);
136
137
        if ('\\' === $pathRegex[0]) {
138
            $routes['dynamicRoutesMap'][0][] = \preg_replace('/\?(?|P<\w+>|<\w+>|\'\w+\')/', '', (empty($hostsRegex) ? '(?:\\/{2}[^\/]+)?' : '\\/{2}(?i:(?|' . \implode('|', $hostsRegex) . '))') . $pathRegex) . '(*:' . $routeId . ')';
139
            $routes['dynamicRoutesMap'][1][$routeId] = $variables;
140
        } else {
141
            $routes['staticRoutesMap'][$pathRegex] = [$routeId, !empty($hostsRegex) ? '#^(?|' . \implode('|', $hostsRegex) . ')$#i' : null, $variables];
142
        }
143
    }
144
145
    private function generateRouteName(Route $route, string $prefix, array $unnamedRoutes): string
146
    {
147
        if (null === $name = $route->get('name')) {
148
            $name = $route->generateRouteName('');
149
150
            if (isset($unnamedRoutes[$name])) {
151
                $name .= ('_' !== $name[-1] ? '_' : '') . ++$unnamedRoutes[$name];
152
            } else {
153
                $unnamedRoutes[$name] = 0;
154
            }
155
        }
156
157
        return $prefix . $name;
158
    }
159
}
160