Completed
Push — master ( 5f700f...192f3f )
by Riikka
03:40
created

RouteDefinitionProvider::getSegmentValueIds()   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 2
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 list of routes per static path.
86
     * @return array[] List of routes per static path
87
     */
88 17
    public function getStaticRoutes(): array
89
    {
90 17
        return $this->staticRoutes;
91
    }
92
93
    /**
94
     * Returns route ids with specific segment count.
95
     * @param int $count The number of segments in the path
96
     * @return int[] List of route ids with specific segment count
97
     */
98 11
    public function getSegmentCountIds(int $count): array
99
    {
100 11
        return $this->segmentCounts[$count] ?? [];
101
    }
102
103
    /**
104
     * Returns route ids with specific value for specific segment.
105
     * @param int $segment The number of the segment
106
     * @param string $value The value for the segment or '/' dynamic segments
107
     * @return int[] List of route ids the match the given criteria
108
     */
109 8
    public function getSegmentValueIds(int $segment, string $value): array
110
    {
111 8
        return $this->segmentValues[$segment][$value] ?? [];
112
    }
113
114
    /**
115
     * Returns a route definition by a specific id.
116
     * @param int $routeId Id of the route definition
117
     * @return RouteDefinition The route definition for the specific id
118
     */
119 16
    public function getRouteDefinition(int $routeId): RouteDefinition
120
    {
121 16
        if (!isset($this->routeDefinitions[$routeId])) {
122 1
            throw new \InvalidArgumentException("Invalid route id '$routeId'");
123
        }
124
125 15
        return RouteDefinition::createFromCache($this->routeDefinitions[$routeId]);
126
    }
127
128
    /**
129
     * Returns a route definition by the name of the route.
130
     * @param string $name The name of the route
131
     * @return RouteDefinition The route definition with the given name
132
     */
133 10
    public function getRouteDefinitionByName(string $name): RouteDefinition
134
    {
135 10
        if (!isset($this->routesByName[$name])) {
136 1
            throw new \InvalidArgumentException("Invalid route name '$name'");
137
        }
138
139 9
        return $this->getRouteDefinition($this->routesByName[$name]);
140
    }
141
}
142