RouteDefinitionProvider::getRoutesBySegmentCount()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Simply\Router;
4
5
/**
6
 * Provides route definitions and matching arrays for the router.
7
 * @author Riikka Kalliomäki <[email protected]>
8
 * @copyright Copyright (c) 2018-2019 Riikka Kalliomäki
9
 * @license http://opensource.org/licenses/mit-license.php MIT License
10
 */
11
class RouteDefinitionProvider
12
{
13
    /** @var int[][] List of static paths to route */
14
    protected $staticRoutes = [];
15
16
    /** @var int[][] List of routes per number of segments */
17
    protected $segmentCounts = [];
18
19
    /** @var int[][][] List of routes by each segment */
20
    protected $segmentValues = [];
21
22
    /** @var array[] Cache of all route definitions */
23
    protected $routeDefinitions = [];
24
25
    /** @var int[] List of routes by their name */
26
    protected $routesByName = [];
27
28
    /**
29
     * Adds a new route definition.
30
     * @param RouteDefinition $definition A new route definition to add
31
     */
32 24
    public function addRouteDefinition(RouteDefinition $definition): void
33
    {
34 24
        $name = $definition->getName();
35
36 24
        if (isset($this->routesByName[$name])) {
37 1
            throw new \InvalidArgumentException("Route with name '$name' already exists");
38
        }
39
40 24
        $routeId = \count($this->routeDefinitions);
41 24
        $segments = $definition->getSegments();
42
43 24
        $this->routeDefinitions[$routeId] = $definition->getDefinitionCache();
44 24
        $this->routesByName[$name] = $routeId;
45
46 24
        if ($definition->isStatic()) {
47 15
            $this->staticRoutes[implode('/', $segments)][] = $routeId;
48 15
            return;
49
        }
50
51 11
        foreach ($segments as $i => $segment) {
52 11
            $this->segmentValues[$i][$segment][$routeId] = $routeId;
53
54 11
            if (!isset($this->segmentCounts[$i])) {
55 11
                $this->segmentCounts[$i] = [];
56
            }
57
        }
58
59 11
        $this->segmentCounts[\count($segments)][$routeId] = $routeId;
60 11
    }
61
62
    /**
63
     * Returns PHP code for cached RouteDefinitionProvider that can be stored in file and included.
64
     * @param callable $encoder Encoding callback for values or null for default
65
     * @return string PHP code for cached RouteDefinitionProvider
66
     */
67 24
    public function getCacheFile(callable $encoder = null): string
68
    {
69 24
        if (\is_null($encoder)) {
70
            $encoder = function ($value): string {
71 24
                return var_export($value, true);
72 24
            };
73
        }
74
75 24
        $statics = $encoder($this->staticRoutes);
76 24
        $counts = $encoder($this->segmentCounts);
77 24
        $values = $encoder($this->segmentValues);
78 24
        $definitions = $encoder($this->routeDefinitions);
79 24
        $names = $encoder($this->routesByName);
80
81
        return <<<TEMPLATE
82
<?php return new class extends \Simply\Router\RouteDefinitionProvider {
83 24
    protected \$staticRoutes = $statics;
84 24
    protected \$segmentCounts = $counts;
85 24
    protected \$segmentValues = $values;
86 24
    protected \$routeDefinitions = $definitions;
87 24
    protected \$routesByName = $names;
88
};
89
TEMPLATE;
90
    }
91
92
    /**
93
     * Returns route ids for routes with specific static path.
94
     * @param string $path The static route path to search
95
     * @return int[] List of route ids with specific static path
96
     */
97 23
    public function getRoutesByStaticPath(string $path): array
98
    {
99 23
        return $this->staticRoutes[$path] ?? [];
100
    }
101
102
    /**
103
     * Returns route ids with specific segment count.
104
     * @param int $count The number of segments in the path
105
     * @return int[] List of route ids with specific segment count
106
     */
107 14
    public function getRoutesBySegmentCount(int $count): array
108
    {
109 14
        return $this->segmentCounts[$count] ?? [];
110
    }
111
112
    /**
113
     * Returns route ids with specific value for specific segment.
114
     * @param int $segment The number of the segment
115
     * @param string $value The value for the segment or '/' dynamic segments
116
     * @return int[] List of route ids the match the given criteria
117
     */
118 14
    public function getRoutesBySegmentValue(int $segment, string $value): array
119
    {
120 14
        return $this->segmentValues[$segment][$value] ?? [];
121
    }
122
123
    /**
124
     * Returns a route definition by a specific id.
125
     * @param int $routeId Id of the route definition
126
     * @return RouteDefinition The route definition for the specific id
127
     */
128 21
    public function getRouteDefinition(int $routeId): RouteDefinition
129
    {
130 21
        if (!isset($this->routeDefinitions[$routeId])) {
131 1
            throw new \InvalidArgumentException("Invalid route id '$routeId'");
132
        }
133
134 20
        return RouteDefinition::createFromCache($this->routeDefinitions[$routeId]);
135
    }
136
137
    /**
138
     * Returns a route definition by the name of the route.
139
     * @param string $name The name of the route
140
     * @return RouteDefinition The route definition with the given name
141
     */
142 14
    public function getRouteDefinitionByName(string $name): RouteDefinition
143
    {
144 14
        if (!isset($this->routesByName[$name])) {
145 1
            throw new \InvalidArgumentException("Invalid route name '$name'");
146
        }
147
148 13
        return $this->getRouteDefinition($this->routesByName[$name]);
149
    }
150
}
151