Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
/**
4
 * Slim Framework (https://slimframework.com)
5
 *
6
 * @license https://github.com/slimphp/Slim/blob/4.x/LICENSE.md (MIT License)
7
 */
8
 
9
declare(strict_types=1);
10
 
11
namespace Slim\Routing;
12
 
13
use Psr\Container\ContainerInterface;
14
use Psr\Http\Message\ResponseFactoryInterface;
15
use RuntimeException;
16
use Slim\Handlers\Strategies\RequestResponse;
17
use Slim\Interfaces\CallableResolverInterface;
18
use Slim\Interfaces\InvocationStrategyInterface;
19
use Slim\Interfaces\RouteCollectorInterface;
20
use Slim\Interfaces\RouteCollectorProxyInterface;
21
use Slim\Interfaces\RouteGroupInterface;
22
use Slim\Interfaces\RouteInterface;
23
use Slim\Interfaces\RouteParserInterface;
24
 
25
use function array_pop;
26
use function dirname;
27
use function file_exists;
28
use function sprintf;
29
use function is_readable;
30
use function is_writable;
31
 
32
/**
33
 * RouteCollector is used to collect routes and route groups
34
 * as well as generate paths and URLs relative to its environment
35
 */
36
class RouteCollector implements RouteCollectorInterface
37
{
38
    protected RouteParserInterface $routeParser;
39
 
40
    protected CallableResolverInterface $callableResolver;
41
 
42
    protected ?ContainerInterface $container = null;
43
 
44
    protected InvocationStrategyInterface $defaultInvocationStrategy;
45
 
46
    /**
47
     * Base path used in pathFor()
48
     */
49
    protected string $basePath = '';
50
 
51
    /**
52
     * Path to fast route cache file. Set to null to disable route caching
53
     */
54
    protected ?string $cacheFile = null;
55
 
56
    /**
57
     * Routes
58
     *
59
     * @var RouteInterface[]
60
     */
61
    protected array $routes = [];
62
 
63
    /**
64
     * Routes indexed by name
65
     *
66
     * @var RouteInterface[]
67
     */
68
    protected array $routesByName = [];
69
 
70
    /**
71
     * Route groups
72
     *
73
     * @var RouteGroupInterface[]
74
     */
75
    protected array $routeGroups = [];
76
 
77
    /**
78
     * Route counter incrementer
79
     */
80
    protected int $routeCounter = 0;
81
 
82
    protected ResponseFactoryInterface $responseFactory;
83
 
84
    public function __construct(
85
        ResponseFactoryInterface $responseFactory,
86
        CallableResolverInterface $callableResolver,
87
        ?ContainerInterface $container = null,
88
        ?InvocationStrategyInterface $defaultInvocationStrategy = null,
89
        ?RouteParserInterface $routeParser = null,
90
        ?string $cacheFile = null
91
    ) {
92
        $this->responseFactory = $responseFactory;
93
        $this->callableResolver = $callableResolver;
94
        $this->container = $container;
95
        $this->defaultInvocationStrategy = $defaultInvocationStrategy ?? new RequestResponse();
96
        $this->routeParser = $routeParser ?? new RouteParser($this);
97
 
98
        if ($cacheFile) {
99
            $this->setCacheFile($cacheFile);
100
        }
101
    }
102
 
103
    public function getRouteParser(): RouteParserInterface
104
    {
105
        return $this->routeParser;
106
    }
107
 
108
    /**
109
     * Get default route invocation strategy
110
     */
111
    public function getDefaultInvocationStrategy(): InvocationStrategyInterface
112
    {
113
        return $this->defaultInvocationStrategy;
114
    }
115
 
116
    public function setDefaultInvocationStrategy(InvocationStrategyInterface $strategy): RouteCollectorInterface
117
    {
118
        $this->defaultInvocationStrategy = $strategy;
119
        return $this;
120
    }
121
 
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function getCacheFile(): ?string
126
    {
127
        return $this->cacheFile;
128
    }
129
 
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function setCacheFile(string $cacheFile): RouteCollectorInterface
134
    {
135
        if (file_exists($cacheFile) && !is_readable($cacheFile)) {
136
            throw new RuntimeException(
137
                sprintf('Route collector cache file `%s` is not readable', $cacheFile)
138
            );
139
        }
140
 
141
        if (!file_exists($cacheFile) && !is_writable(dirname($cacheFile))) {
142
            throw new RuntimeException(
143
                sprintf('Route collector cache file directory `%s` is not writable', dirname($cacheFile))
144
            );
145
        }
146
 
147
        $this->cacheFile = $cacheFile;
148
        return $this;
149
    }
150
 
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public function getBasePath(): string
155
    {
156
        return $this->basePath;
157
    }
158
 
159
    /**
160
     * Set the base path used in urlFor()
161
     */
162
    public function setBasePath(string $basePath): RouteCollectorInterface
163
    {
164
        $this->basePath = $basePath;
165
 
166
        return $this;
167
    }
168
 
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function getRoutes(): array
173
    {
174
        return $this->routes;
175
    }
176
 
177
    /**
178
     * {@inheritdoc}
179
     */
180
    public function removeNamedRoute(string $name): RouteCollectorInterface
181
    {
182
        $route = $this->getNamedRoute($name);
183
 
184
        unset($this->routesByName[$route->getName()], $this->routes[$route->getIdentifier()]);
185
        return $this;
186
    }
187
 
188
    /**
189
     * {@inheritdoc}
190
     */
191
    public function getNamedRoute(string $name): RouteInterface
192
    {
193
        if (isset($this->routesByName[$name])) {
194
            $route = $this->routesByName[$name];
195
            if ($route->getName() === $name) {
196
                return $route;
197
            }
198
 
199
            unset($this->routesByName[$name]);
200
        }
201
 
202
        foreach ($this->routes as $route) {
203
            if ($name === $route->getName()) {
204
                $this->routesByName[$name] = $route;
205
                return $route;
206
            }
207
        }
208
 
209
        throw new RuntimeException('Named route does not exist for name: ' . $name);
210
    }
211
 
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function lookupRoute(string $identifier): RouteInterface
216
    {
217
        if (!isset($this->routes[$identifier])) {
218
            throw new RuntimeException('Route not found, looks like your route cache is stale.');
219
        }
220
        return $this->routes[$identifier];
221
    }
222
 
223
    /**
224
     * {@inheritdoc}
225
     */
226
    public function group(string $pattern, $callable): RouteGroupInterface
227
    {
228
        $routeGroup = $this->createGroup($pattern, $callable);
229
        $this->routeGroups[] = $routeGroup;
230
 
231
        $routeGroup->collectRoutes();
232
        array_pop($this->routeGroups);
233
 
234
        return $routeGroup;
235
    }
236
 
237
    /**
238
     * @param string|callable $callable
239
     */
240
    protected function createGroup(string $pattern, $callable): RouteGroupInterface
241
    {
242
        $routeCollectorProxy = $this->createProxy($pattern);
243
        return new RouteGroup($pattern, $callable, $this->callableResolver, $routeCollectorProxy);
244
    }
245
 
246
    protected function createProxy(string $pattern): RouteCollectorProxyInterface
247
    {
248
        return new RouteCollectorProxy(
249
            $this->responseFactory,
250
            $this->callableResolver,
251
            $this->container,
252
            $this,
253
            $pattern
254
        );
255
    }
256
 
257
    /**
258
     * {@inheritdoc}
259
     */
260
    public function map(array $methods, string $pattern, $handler): RouteInterface
261
    {
262
        $route = $this->createRoute($methods, $pattern, $handler);
263
        $this->routes[$route->getIdentifier()] = $route;
264
 
265
        $routeName = $route->getName();
266
        if ($routeName !== null && !isset($this->routesByName[$routeName])) {
267
            $this->routesByName[$routeName] = $route;
268
        }
269
 
270
        $this->routeCounter++;
271
 
272
        return $route;
273
    }
274
 
275
    /**
276
     * @param string[]        $methods
277
     * @param callable|string $callable
278
     */
279
    protected function createRoute(array $methods, string $pattern, $callable): RouteInterface
280
    {
281
        return new Route(
282
            $methods,
283
            $pattern,
284
            $callable,
285
            $this->responseFactory,
286
            $this->callableResolver,
287
            $this->container,
288
            $this->defaultInvocationStrategy,
289
            $this->routeGroups,
290
            $this->routeCounter
291
        );
292
    }
293
}