Completed
Push — master ( 192f3f...8b3927 )
by Riikka
02:18
created

RouteDefinitionProvider::getRoutesByStaticPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
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 Riikka Kalliomäki
9
 * @license http://opensource.org/licenses/mit-license.php MIT License
10
 */
11
class RouteDefinitionProvider
12
{
13
    /** @var array<int[]> List of static paths to route */
14
    protected $staticRoutes = [];
15
16
    /** @var array<int[]> List of routes per number of segments */
17
    protected $segmentCounts = [];
18
19
    /** @var array<array<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 18
    public function addRouteDefinition(RouteDefinition $definition): void
33
    {
34 18
        $name = $definition->getName();
35
36 18
        if (isset($this->routesByName[$name])) {
37 1
            throw new \InvalidArgumentException("Route with name '$name' already exists");
38
        }
39
40 18
        $routeId = \count($this->routeDefinitions);
41 18
        $segments = $definition->getSegments();
42
43 18
        $this->routeDefinitions[$routeId] = $definition->getDefinitionCache();
44 18
        $this->routesByName[$name] = $routeId;
45
46 18
        if ($definition->isStatic()) {
47 10
            $this->staticRoutes[implode('/', $segments)][] = $routeId;
48 10
            return;
49
        }
50
51 9
        foreach ($segments as $i => $segment) {
52 9
            $this->segmentValues[$i][$segment][$routeId] = $routeId;
53
        }
54
55 9
        $this->segmentCounts += array_fill(0, \count($segments) + 1, []);
56 9
        $this->segmentCounts[\count($segments)][$routeId] = $routeId;
57 9
    }
58
59
    /**
60
     * Returns PHP code for cached RouteDefinitionProvider that can be stored in file and included.
61
     * @return string PHP code for cached RouteDefinitionProvider
62
     */
63 18
    public function getCacheFile(): string
64
    {
65
        $template = <<<'TEMPLATE'
66 18
<?php return new class extends \Simply\Router\RouteDefinitionProvider {
67
    protected $staticRoutes = ['STATICS'];
68
    protected $segmentCounts = ['COUNTS'];
69
    protected $segmentValues = ['VALUES'];
70
    protected $routeDefinitions = ['DEFINITIONS'];
71
    protected $routesByName = ['NAMES'];
72
};
73
TEMPLATE;
74
75 18
        return strtr($template, [
76 18
            "['STATICS']" => var_export($this->staticRoutes, true),
77 18
            "['COUNTS']" => var_export($this->segmentCounts, true),
78 18
            "['VALUES']" => var_export($this->segmentValues, true),
79 18
            "['DEFINITIONS']" => var_export($this->routeDefinitions, true),
80 18
            "['NAMES']" => var_export($this->routesByName, true),
81
        ]);
82
    }
83
84
    /**
85
     * Returns route ids for routes with specific static path.
86
     * @param string $path The static route path to search
87
     * @return int[] List of route ids with specific static path
88
     */
89 17
    public function getRoutesByStaticPath(string $path): array
90
    {
91 17
        return $this->staticRoutes[$path] ?? [];
92
    }
93
94
    /**
95
     * Returns route ids with specific segment count.
96
     * @param int $count The number of segments in the path
97
     * @return int[] List of route ids with specific segment count
98
     */
99 11
    public function getRoutesBySegmentCount(int $count): array
100
    {
101 11
        return $this->segmentCounts[$count] ?? [];
102
    }
103
104
    /**
105
     * Returns route ids with specific value for specific segment.
106
     * @param int $segment The number of the segment
107
     * @param string $value The value for the segment or '/' dynamic segments
108
     * @return int[] List of route ids the match the given criteria
109
     */
110 8
    public function getRoutesBySegmentValue(int $segment, string $value): array
111
    {
112 8
        return $this->segmentValues[$segment][$value] ?? [];
113
    }
114
115
    /**
116
     * Returns a route definition by a specific id.
117
     * @param int $routeId Id of the route definition
118
     * @return RouteDefinition The route definition for the specific id
119
     */
120 16
    public function getRouteDefinition(int $routeId): RouteDefinition
121
    {
122 16
        if (!isset($this->routeDefinitions[$routeId])) {
123 1
            throw new \InvalidArgumentException("Invalid route id '$routeId'");
124
        }
125
126 15
        return RouteDefinition::createFromCache($this->routeDefinitions[$routeId]);
127
    }
128
129
    /**
130
     * Returns a route definition by the name of the route.
131
     * @param string $name The name of the route
132
     * @return RouteDefinition The route definition with the given name
133
     */
134 10
    public function getRouteDefinitionByName(string $name): RouteDefinition
135
    {
136 10
        if (!isset($this->routesByName[$name])) {
137 1
            throw new \InvalidArgumentException("Invalid route name '$name'");
138
        }
139
140 9
        return $this->getRouteDefinition($this->routesByName[$name]);
141
    }
142
}
143