Vendor lock
This commit is contained in:
5
vendor/nikic/fast-route/.gitignore
vendored
Normal file
5
vendor/nikic/fast-route/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/vendor/
|
||||
.idea/
|
||||
|
||||
# ignore lock file since we have no extra dependencies
|
||||
composer.lock
|
1
vendor/nikic/fast-route/.hhconfig
vendored
Normal file
1
vendor/nikic/fast-route/.hhconfig
vendored
Normal file
@ -0,0 +1 @@
|
||||
assume_php=false
|
20
vendor/nikic/fast-route/.travis.yml
vendored
Normal file
20
vendor/nikic/fast-route/.travis.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
sudo: false
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- hhvm
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpunit
|
||||
|
||||
before_install:
|
||||
- travis_retry composer self-update
|
||||
|
||||
install:
|
||||
- composer install
|
126
vendor/nikic/fast-route/FastRoute.hhi
vendored
Normal file
126
vendor/nikic/fast-route/FastRoute.hhi
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
<?hh // decl
|
||||
|
||||
namespace FastRoute {
|
||||
class BadRouteException extends \LogicException {
|
||||
}
|
||||
|
||||
interface RouteParser {
|
||||
public function parse(string $route): array<array>;
|
||||
}
|
||||
|
||||
class RouteCollector {
|
||||
public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator);
|
||||
public function addRoute(mixed $httpMethod, string $route, mixed $handler): void;
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
class Route {
|
||||
public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables);
|
||||
public function matches(string $str): bool;
|
||||
}
|
||||
|
||||
interface DataGenerator {
|
||||
public function addRoute(string $httpMethod, array $routeData, mixed $handler);
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
interface Dispatcher {
|
||||
const int NOT_FOUND = 0;
|
||||
const int FOUND = 1;
|
||||
const int METHOD_NOT_ALLOWED = 2;
|
||||
public function dispatch(string $httpMethod, string $uri): array;
|
||||
}
|
||||
|
||||
function simpleDispatcher(
|
||||
(function(RouteCollector): void) $routeDefinitionCallback,
|
||||
shape(
|
||||
?'routeParser' => classname<RouteParser>,
|
||||
?'dataGenerator' => classname<DataGenerator>,
|
||||
?'dispatcher' => classname<Dispatcher>,
|
||||
?'routeCollector' => classname<RouteCollector>,
|
||||
) $options = shape()): Dispatcher;
|
||||
|
||||
function cachedDispatcher(
|
||||
(function(RouteCollector): void) $routeDefinitionCallback,
|
||||
shape(
|
||||
?'routeParser' => classname<RouteParser>,
|
||||
?'dataGenerator' => classname<DataGenerator>,
|
||||
?'dispatcher' => classname<Dispatcher>,
|
||||
?'routeCollector' => classname<RouteCollector>,
|
||||
?'cacheDisabled' => bool,
|
||||
?'cacheFile' => string,
|
||||
) $options = shape()): Dispatcher;
|
||||
}
|
||||
|
||||
namespace FastRoute\DataGenerator {
|
||||
abstract class RegexBasedAbstract implements \FastRoute\DataGenerator {
|
||||
protected abstract function getApproxChunkSize();
|
||||
protected abstract function processChunk($regexToRoutesMap);
|
||||
|
||||
public function addRoute(string $httpMethod, array $routeData, mixed $handler): void;
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FastRoute\Dispatcher {
|
||||
abstract class RegexBasedAbstract implements \FastRoute\Dispatcher {
|
||||
protected abstract function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
|
||||
public function dispatch(string $httpMethod, string $uri): array;
|
||||
}
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FastRoute\RouteParser {
|
||||
class Std implements \FastRoute\RouteParser {
|
||||
const string VARIABLE_REGEX = <<<'REGEX'
|
||||
\{
|
||||
\s* ([a-zA-Z][a-zA-Z0-9_]*) \s*
|
||||
(?:
|
||||
: \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
|
||||
)?
|
||||
\}
|
||||
REGEX;
|
||||
const string DEFAULT_DISPATCH_REGEX = '[^/]+';
|
||||
public function parse(string $route): array<array>;
|
||||
}
|
||||
}
|
31
vendor/nikic/fast-route/LICENSE
vendored
Normal file
31
vendor/nikic/fast-route/LICENSE
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
Copyright (c) 2013 by Nikita Popov.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
313
vendor/nikic/fast-route/README.md
vendored
Normal file
313
vendor/nikic/fast-route/README.md
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
FastRoute - Fast request router for PHP
|
||||
=======================================
|
||||
|
||||
This library provides a fast implementation of a regular expression based router. [Blog post explaining how the
|
||||
implementation works and why it is fast.][blog_post]
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
To install with composer:
|
||||
|
||||
```sh
|
||||
composer require nikic/fast-route
|
||||
```
|
||||
|
||||
Requires PHP 5.4 or newer.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here's a basic usage example:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require '/path/to/vendor/autoload.php';
|
||||
|
||||
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
$r->addRoute('GET', '/users', 'get_all_users_handler');
|
||||
// {id} must be a number (\d+)
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler');
|
||||
// The /{title} suffix is optional
|
||||
$r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler');
|
||||
});
|
||||
|
||||
// Fetch method and URI from somewhere
|
||||
$httpMethod = $_SERVER['REQUEST_METHOD'];
|
||||
$uri = $_SERVER['REQUEST_URI'];
|
||||
|
||||
// Strip query string (?foo=bar) and decode URI
|
||||
if (false !== $pos = strpos($uri, '?')) {
|
||||
$uri = substr($uri, 0, $pos);
|
||||
}
|
||||
$uri = rawurldecode($uri);
|
||||
|
||||
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
|
||||
switch ($routeInfo[0]) {
|
||||
case FastRoute\Dispatcher::NOT_FOUND:
|
||||
// ... 404 Not Found
|
||||
break;
|
||||
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
|
||||
$allowedMethods = $routeInfo[1];
|
||||
// ... 405 Method Not Allowed
|
||||
break;
|
||||
case FastRoute\Dispatcher::FOUND:
|
||||
$handler = $routeInfo[1];
|
||||
$vars = $routeInfo[2];
|
||||
// ... call $handler with $vars
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
### Defining routes
|
||||
|
||||
The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts
|
||||
a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling
|
||||
`addRoute()` on the collector instance:
|
||||
|
||||
```php
|
||||
$r->addRoute($method, $routePattern, $handler);
|
||||
```
|
||||
|
||||
The `$method` is an uppercase HTTP method string for which a certain route should match. It
|
||||
is possible to specify multiple valid methods using an array:
|
||||
|
||||
```php
|
||||
// These two calls
|
||||
$r->addRoute('GET', '/test', 'handler');
|
||||
$r->addRoute('POST', '/test', 'handler');
|
||||
// Are equivalent to this one call
|
||||
$r->addRoute(['GET', 'POST'], '/test', 'handler');
|
||||
```
|
||||
|
||||
By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
|
||||
and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify
|
||||
a custom pattern by writing `{bar:[0-9]+}`. Some examples:
|
||||
|
||||
```php
|
||||
// Matches /user/42, but not /user/xyz
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
|
||||
|
||||
// Matches /user/foobar, but not /user/foo/bar
|
||||
$r->addRoute('GET', '/user/{name}', 'handler');
|
||||
|
||||
// Matches /user/foo/bar as well
|
||||
$r->addRoute('GET', '/user/{name:.+}', 'handler');
|
||||
```
|
||||
|
||||
Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}`
|
||||
is not a valid placeholder, because `()` is a capturing group. Instead you can use either
|
||||
`{lang:en|de}` or `{lang:(?:en|de)}`.
|
||||
|
||||
Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
|
||||
will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position,
|
||||
not in the middle of a route.
|
||||
|
||||
```php
|
||||
// This route
|
||||
$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
|
||||
// Is equivalent to these two routes
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
|
||||
$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler');
|
||||
|
||||
// Multiple nested optional parts are possible as well
|
||||
$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');
|
||||
|
||||
// This route is NOT valid, because optional parts can only occur at the end
|
||||
$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');
|
||||
```
|
||||
|
||||
The `$handler` parameter does not necessarily have to be a callback, it could also be a controller
|
||||
class name or any other kind of data you wish to associate with the route. FastRoute only tells you
|
||||
which handler corresponds to your URI, how you interpret it is up to you.
|
||||
|
||||
#### Shorcut methods for common request methods
|
||||
|
||||
For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example:
|
||||
|
||||
```php
|
||||
$r->get('/get-route', 'get_handler');
|
||||
$r->post('/post-route', 'post_handler');
|
||||
```
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
```php
|
||||
$r->addRoute('GET', '/get-route', 'get_handler');
|
||||
$r->addRoute('POST', '/post-route', 'post_handler');
|
||||
```
|
||||
|
||||
#### Route Groups
|
||||
|
||||
Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix.
|
||||
|
||||
For example, defining your routes as:
|
||||
|
||||
```php
|
||||
$r->addGroup('/admin', function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/do-something', 'handler');
|
||||
$r->addRoute('GET', '/do-another-thing', 'handler');
|
||||
$r->addRoute('GET', '/do-something-else', 'handler');
|
||||
});
|
||||
```
|
||||
|
||||
Will have the same result as:
|
||||
|
||||
```php
|
||||
$r->addRoute('GET', '/admin/do-something', 'handler');
|
||||
$r->addRoute('GET', '/admin/do-another-thing', 'handler');
|
||||
$r->addRoute('GET', '/admin/do-something-else', 'handler');
|
||||
```
|
||||
|
||||
Nested groups are also supported, in which case the prefixes of all the nested groups are combined.
|
||||
|
||||
### Caching
|
||||
|
||||
The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless
|
||||
caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated
|
||||
routing data and construct the dispatcher from the cached information:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$dispatcher = FastRoute\cachedDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
}, [
|
||||
'cacheFile' => __DIR__ . '/route.cache', /* required */
|
||||
'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */
|
||||
]);
|
||||
```
|
||||
|
||||
The second parameter to the function is an options array, which can be used to specify the cache
|
||||
file location, among other things.
|
||||
|
||||
### Dispatching a URI
|
||||
|
||||
A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method
|
||||
accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them
|
||||
appropriately) is your job - this library is not bound to the PHP web SAPIs.
|
||||
|
||||
The `dispatch()` method returns an array whose first element contains a status code. It is one
|
||||
of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the
|
||||
method not allowed status the second array element contains a list of HTTP methods allowed for
|
||||
the supplied URI. For example:
|
||||
|
||||
[FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']]
|
||||
|
||||
> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the
|
||||
`Allow:` header to detail available methods for the requested resource. Applications using FastRoute
|
||||
should use the second array element to add this header when relaying a 405 response.
|
||||
|
||||
For the found status the second array element is the handler that was associated with the route
|
||||
and the third array element is a dictionary of placeholder names to their values. For example:
|
||||
|
||||
/* Routing against GET /user/nikic/42 */
|
||||
|
||||
[FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']]
|
||||
|
||||
### Overriding the route parser and dispatcher
|
||||
|
||||
The routing process makes use of three components: A route parser, a data generator and a
|
||||
dispatcher. The three components adhere to the following interfaces:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface RouteParser {
|
||||
public function parse($route);
|
||||
}
|
||||
|
||||
interface DataGenerator {
|
||||
public function addRoute($httpMethod, $routeData, $handler);
|
||||
public function getData();
|
||||
}
|
||||
|
||||
interface Dispatcher {
|
||||
const NOT_FOUND = 0, FOUND = 1, METHOD_NOT_ALLOWED = 2;
|
||||
|
||||
public function dispatch($httpMethod, $uri);
|
||||
}
|
||||
```
|
||||
|
||||
The route parser takes a route pattern string and converts it into an array of route infos, where
|
||||
each route info is again an array of it's parts. The structure is best understood using an example:
|
||||
|
||||
/* The route /user/{id:\d+}[/{name}] converts to the following array: */
|
||||
[
|
||||
[
|
||||
'/user/',
|
||||
['id', '\d+'],
|
||||
],
|
||||
[
|
||||
'/user/',
|
||||
['id', '\d+'],
|
||||
'/',
|
||||
['name', '[^/]+'],
|
||||
],
|
||||
]
|
||||
|
||||
This array can then be passed to the `addRoute()` method of a data generator. After all routes have
|
||||
been added the `getData()` of the generator is invoked, which returns all the routing data required
|
||||
by the dispatcher. The format of this data is not further specified - it is tightly coupled to
|
||||
the corresponding dispatcher.
|
||||
|
||||
The dispatcher accepts the routing data via a constructor and provides a `dispatch()` method, which
|
||||
you're already familiar with.
|
||||
|
||||
The route parser can be overwritten individually (to make use of some different pattern syntax),
|
||||
however the data generator and dispatcher should always be changed as a pair, as the output from
|
||||
the former is tightly coupled to the input of the latter. The reason the generator and the
|
||||
dispatcher are separate is that only the latter is needed when using caching (as the output of
|
||||
the former is what is being cached.)
|
||||
|
||||
When using the `simpleDispatcher` / `cachedDispatcher` functions from above the override happens
|
||||
through the options array:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
/* ... */
|
||||
}, [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
]);
|
||||
```
|
||||
|
||||
The above options array corresponds to the defaults. By replacing `GroupCountBased` by
|
||||
`GroupPosBased` you could switch to a different dispatching strategy.
|
||||
|
||||
### A Note on HEAD Requests
|
||||
|
||||
The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]:
|
||||
|
||||
> The methods GET and HEAD MUST be supported by all general-purpose servers
|
||||
|
||||
To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an
|
||||
available GET route for a given resource. The PHP web SAPI transparently removes the entity body
|
||||
from HEAD responses so this behavior has no effect on the vast majority of users.
|
||||
|
||||
However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST
|
||||
NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is
|
||||
*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases.
|
||||
|
||||
Finally, note that applications MAY always specify their own HEAD method route for a given
|
||||
resource to bypass this behavior entirely.
|
||||
|
||||
### Credits
|
||||
|
||||
This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server.
|
||||
|
||||
A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey].
|
||||
|
||||
|
||||
[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1"
|
||||
[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html
|
||||
[levi]: https://github.com/morrisonlevi
|
||||
[rdlowrey]: https://github.com/rdlowrey
|
24
vendor/nikic/fast-route/composer.json
vendored
Normal file
24
vendor/nikic/fast-route/composer.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": ["routing", "router"],
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": ["src/functions.php"]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35|~5.7"
|
||||
}
|
||||
}
|
24
vendor/nikic/fast-route/phpunit.xml
vendored
Normal file
24
vendor/nikic/fast-route/phpunit.xml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="FastRoute Tests">
|
||||
<directory>./test/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
28
vendor/nikic/fast-route/psalm.xml
vendored
Normal file
28
vendor/nikic/fast-route/psalm.xml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
name="Example Psalm config with recommended defaults"
|
||||
stopOnFirstError="false"
|
||||
useDocblockTypes="true"
|
||||
totallyTyped="false"
|
||||
requireVoidReturnType="false"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info" />
|
||||
<MissingConstructor errorLevel="info" />
|
||||
</issueHandlers>
|
||||
</psalm>
|
7
vendor/nikic/fast-route/src/BadRouteException.php
vendored
Normal file
7
vendor/nikic/fast-route/src/BadRouteException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class BadRouteException extends \LogicException
|
||||
{
|
||||
}
|
26
vendor/nikic/fast-route/src/DataGenerator.php
vendored
Normal file
26
vendor/nikic/fast-route/src/DataGenerator.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface DataGenerator
|
||||
{
|
||||
/**
|
||||
* Adds a route to the data generator. The route data uses the
|
||||
* same format that is returned by RouterParser::parser().
|
||||
*
|
||||
* The handler doesn't necessarily need to be a callable, it
|
||||
* can be arbitrary data that will be returned when the route
|
||||
* matches.
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param array $routeData
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function addRoute($httpMethod, $routeData, $handler);
|
||||
|
||||
/**
|
||||
* Returns dispatcher data in some unspecified format, which
|
||||
* depends on the used method of dispatch.
|
||||
*/
|
||||
public function getData();
|
||||
}
|
31
vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php
vendored
Normal file
31
vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract
|
||||
{
|
||||
protected function getApproxChunkSize()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap)
|
||||
{
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
|
||||
$suffixLen = 0;
|
||||
$suffix = '';
|
||||
$count = count($regexToRoutesMap);
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$suffixLen++;
|
||||
$suffix .= "\t";
|
||||
|
||||
$regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})';
|
||||
$routeMap[$suffix] = [$route->handler, $route->variables];
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
30
vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php
vendored
Normal file
30
vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract
|
||||
{
|
||||
protected function getApproxChunkSize()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap)
|
||||
{
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$numGroups = 0;
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$numVariables = count($route->variables);
|
||||
$numGroups = max($numGroups, $numVariables);
|
||||
|
||||
$regexes[] = $regex . str_repeat('()', $numGroups - $numVariables);
|
||||
$routeMap[$numGroups + 1] = [$route->handler, $route->variables];
|
||||
|
||||
++$numGroups;
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
27
vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php
vendored
Normal file
27
vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract
|
||||
{
|
||||
protected function getApproxChunkSize()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap)
|
||||
{
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$offset = 1;
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$regexes[] = $regex;
|
||||
$routeMap[$offset] = [$route->handler, $route->variables];
|
||||
|
||||
$offset += count($route->variables);
|
||||
}
|
||||
|
||||
$regex = '~^(?:' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
27
vendor/nikic/fast-route/src/DataGenerator/MarkBased.php
vendored
Normal file
27
vendor/nikic/fast-route/src/DataGenerator/MarkBased.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class MarkBased extends RegexBasedAbstract
|
||||
{
|
||||
protected function getApproxChunkSize()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap)
|
||||
{
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$markName = 'a';
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$regexes[] = $regex . '(*MARK:' . $markName . ')';
|
||||
$routeMap[$markName] = [$route->handler, $route->variables];
|
||||
|
||||
++$markName;
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
186
vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php
vendored
Normal file
186
vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
use FastRoute\BadRouteException;
|
||||
use FastRoute\DataGenerator;
|
||||
use FastRoute\Route;
|
||||
|
||||
abstract class RegexBasedAbstract implements DataGenerator
|
||||
{
|
||||
/** @var mixed[][] */
|
||||
protected $staticRoutes = [];
|
||||
|
||||
/** @var Route[][] */
|
||||
protected $methodToRegexToRoutesMap = [];
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
abstract protected function getApproxChunkSize();
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
abstract protected function processChunk($regexToRoutesMap);
|
||||
|
||||
public function addRoute($httpMethod, $routeData, $handler)
|
||||
{
|
||||
if ($this->isStaticRoute($routeData)) {
|
||||
$this->addStaticRoute($httpMethod, $routeData, $handler);
|
||||
} else {
|
||||
$this->addVariableRoute($httpMethod, $routeData, $handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
if (empty($this->methodToRegexToRoutesMap)) {
|
||||
return [$this->staticRoutes, []];
|
||||
}
|
||||
|
||||
return [$this->staticRoutes, $this->generateVariableRouteData()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function generateVariableRouteData()
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) {
|
||||
$chunkSize = $this->computeChunkSize(count($regexToRoutesMap));
|
||||
$chunks = array_chunk($regexToRoutesMap, $chunkSize, true);
|
||||
$data[$method] = array_map([$this, 'processChunk'], $chunks);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int
|
||||
* @return int
|
||||
*/
|
||||
private function computeChunkSize($count)
|
||||
{
|
||||
$numParts = max(1, round($count / $this->getApproxChunkSize()));
|
||||
return (int) ceil($count / $numParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[]
|
||||
* @return bool
|
||||
*/
|
||||
private function isStaticRoute($routeData)
|
||||
{
|
||||
return count($routeData) === 1 && is_string($routeData[0]);
|
||||
}
|
||||
|
||||
private function addStaticRoute($httpMethod, $routeData, $handler)
|
||||
{
|
||||
$routeStr = $routeData[0];
|
||||
|
||||
if (isset($this->staticRoutes[$httpMethod][$routeStr])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot register two routes matching "%s" for method "%s"',
|
||||
$routeStr, $httpMethod
|
||||
));
|
||||
}
|
||||
|
||||
if (isset($this->methodToRegexToRoutesMap[$httpMethod])) {
|
||||
foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) {
|
||||
if ($route->matches($routeStr)) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"',
|
||||
$routeStr, $route->regex, $httpMethod
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->staticRoutes[$httpMethod][$routeStr] = $handler;
|
||||
}
|
||||
|
||||
private function addVariableRoute($httpMethod, $routeData, $handler)
|
||||
{
|
||||
list($regex, $variables) = $this->buildRegexForRoute($routeData);
|
||||
|
||||
if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot register two routes matching "%s" for method "%s"',
|
||||
$regex, $httpMethod
|
||||
));
|
||||
}
|
||||
|
||||
$this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route(
|
||||
$httpMethod, $handler, $regex, $variables
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[]
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function buildRegexForRoute($routeData)
|
||||
{
|
||||
$regex = '';
|
||||
$variables = [];
|
||||
foreach ($routeData as $part) {
|
||||
if (is_string($part)) {
|
||||
$regex .= preg_quote($part, '~');
|
||||
continue;
|
||||
}
|
||||
|
||||
list($varName, $regexPart) = $part;
|
||||
|
||||
if (isset($variables[$varName])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot use the same placeholder "%s" twice', $varName
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->regexHasCapturingGroups($regexPart)) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Regex "%s" for parameter "%s" contains a capturing group',
|
||||
$regexPart, $varName
|
||||
));
|
||||
}
|
||||
|
||||
$variables[$varName] = $varName;
|
||||
$regex .= '(' . $regexPart . ')';
|
||||
}
|
||||
|
||||
return [$regex, $variables];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
private function regexHasCapturingGroups($regex)
|
||||
{
|
||||
if (false === strpos($regex, '(')) {
|
||||
// Needs to have at least a ( to contain a capturing group
|
||||
return false;
|
||||
}
|
||||
|
||||
// Semi-accurate detection for capturing groups
|
||||
return (bool) preg_match(
|
||||
'~
|
||||
(?:
|
||||
\(\?\(
|
||||
| \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \]
|
||||
| \\\\ .
|
||||
) (*SKIP)(*FAIL) |
|
||||
\(
|
||||
(?!
|
||||
\? (?! <(?![!=]) | P< | \' )
|
||||
| \*
|
||||
)
|
||||
~x',
|
||||
$regex
|
||||
);
|
||||
}
|
||||
}
|
26
vendor/nikic/fast-route/src/Dispatcher.php
vendored
Normal file
26
vendor/nikic/fast-route/src/Dispatcher.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface Dispatcher
|
||||
{
|
||||
const NOT_FOUND = 0;
|
||||
const FOUND = 1;
|
||||
const METHOD_NOT_ALLOWED = 2;
|
||||
|
||||
/**
|
||||
* Dispatches against the provided HTTP method verb and URI.
|
||||
*
|
||||
* Returns array with one of the following formats:
|
||||
*
|
||||
* [self::NOT_FOUND]
|
||||
* [self::METHOD_NOT_ALLOWED, ['GET', 'OTHER_ALLOWED_METHODS']]
|
||||
* [self::FOUND, $handler, ['varName' => 'value', ...]]
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param string $uri
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dispatch($httpMethod, $uri);
|
||||
}
|
31
vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php
vendored
Normal file
31
vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract
|
||||
{
|
||||
public function __construct($data)
|
||||
{
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri)
|
||||
{
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][end($matches)];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
31
vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php
vendored
Normal file
31
vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract
|
||||
{
|
||||
public function __construct($data)
|
||||
{
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri)
|
||||
{
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][count($matches)];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
33
vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php
vendored
Normal file
33
vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract
|
||||
{
|
||||
public function __construct($data)
|
||||
{
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri)
|
||||
{
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// find first non-empty match
|
||||
for ($i = 1; '' === $matches[$i]; ++$i);
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][$i];
|
||||
|
||||
$vars = [];
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[$i++];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
31
vendor/nikic/fast-route/src/Dispatcher/MarkBased.php
vendored
Normal file
31
vendor/nikic/fast-route/src/Dispatcher/MarkBased.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class MarkBased extends RegexBasedAbstract
|
||||
{
|
||||
public function __construct($data)
|
||||
{
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri)
|
||||
{
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][$matches['MARK']];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
88
vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php
vendored
Normal file
88
vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
use FastRoute\Dispatcher;
|
||||
|
||||
abstract class RegexBasedAbstract implements Dispatcher
|
||||
{
|
||||
/** @var mixed[][] */
|
||||
protected $staticRouteMap = [];
|
||||
|
||||
/** @var mixed[] */
|
||||
protected $variableRouteData = [];
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
abstract protected function dispatchVariableRoute($routeData, $uri);
|
||||
|
||||
public function dispatch($httpMethod, $uri)
|
||||
{
|
||||
if (isset($this->staticRouteMap[$httpMethod][$uri])) {
|
||||
$handler = $this->staticRouteMap[$httpMethod][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
|
||||
$varRouteData = $this->variableRouteData;
|
||||
if (isset($varRouteData[$httpMethod])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// For HEAD requests, attempt fallback to GET
|
||||
if ($httpMethod === 'HEAD') {
|
||||
if (isset($this->staticRouteMap['GET'][$uri])) {
|
||||
$handler = $this->staticRouteMap['GET'][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
if (isset($varRouteData['GET'])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData['GET'], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing else matches, try fallback routes
|
||||
if (isset($this->staticRouteMap['*'][$uri])) {
|
||||
$handler = $this->staticRouteMap['*'][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
if (isset($varRouteData['*'])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData['*'], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Find allowed methods for this URI by matching against all other HTTP methods as well
|
||||
$allowedMethods = [];
|
||||
|
||||
foreach ($this->staticRouteMap as $method => $uriMap) {
|
||||
if ($method !== $httpMethod && isset($uriMap[$uri])) {
|
||||
$allowedMethods[] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($varRouteData as $method => $routeData) {
|
||||
if ($method === $httpMethod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->dispatchVariableRoute($routeData, $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
$allowedMethods[] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no allowed methods the route simply does not exist
|
||||
if ($allowedMethods) {
|
||||
return [self::METHOD_NOT_ALLOWED, $allowedMethods];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
47
vendor/nikic/fast-route/src/Route.php
vendored
Normal file
47
vendor/nikic/fast-route/src/Route.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class Route
|
||||
{
|
||||
/** @var string */
|
||||
public $httpMethod;
|
||||
|
||||
/** @var string */
|
||||
public $regex;
|
||||
|
||||
/** @var array */
|
||||
public $variables;
|
||||
|
||||
/** @var mixed */
|
||||
public $handler;
|
||||
|
||||
/**
|
||||
* Constructs a route (value object).
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param mixed $handler
|
||||
* @param string $regex
|
||||
* @param array $variables
|
||||
*/
|
||||
public function __construct($httpMethod, $handler, $regex, $variables)
|
||||
{
|
||||
$this->httpMethod = $httpMethod;
|
||||
$this->handler = $handler;
|
||||
$this->regex = $regex;
|
||||
$this->variables = $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this route matches the given string.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matches($str)
|
||||
{
|
||||
$regex = '~^' . $this->regex . '$~';
|
||||
return (bool) preg_match($regex, $str);
|
||||
}
|
||||
}
|
152
vendor/nikic/fast-route/src/RouteCollector.php
vendored
Normal file
152
vendor/nikic/fast-route/src/RouteCollector.php
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class RouteCollector
|
||||
{
|
||||
/** @var RouteParser */
|
||||
protected $routeParser;
|
||||
|
||||
/** @var DataGenerator */
|
||||
protected $dataGenerator;
|
||||
|
||||
/** @var string */
|
||||
protected $currentGroupPrefix;
|
||||
|
||||
/**
|
||||
* Constructs a route collector.
|
||||
*
|
||||
* @param RouteParser $routeParser
|
||||
* @param DataGenerator $dataGenerator
|
||||
*/
|
||||
public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator)
|
||||
{
|
||||
$this->routeParser = $routeParser;
|
||||
$this->dataGenerator = $dataGenerator;
|
||||
$this->currentGroupPrefix = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route to the collection.
|
||||
*
|
||||
* The syntax used in the $route string depends on the used route parser.
|
||||
*
|
||||
* @param string|string[] $httpMethod
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function addRoute($httpMethod, $route, $handler)
|
||||
{
|
||||
$route = $this->currentGroupPrefix . $route;
|
||||
$routeDatas = $this->routeParser->parse($route);
|
||||
foreach ((array) $httpMethod as $method) {
|
||||
foreach ($routeDatas as $routeData) {
|
||||
$this->dataGenerator->addRoute($method, $routeData, $handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a route group with a common prefix.
|
||||
*
|
||||
* All routes created in the passed callback will have the given group prefix prepended.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function addGroup($prefix, callable $callback)
|
||||
{
|
||||
$previousGroupPrefix = $this->currentGroupPrefix;
|
||||
$this->currentGroupPrefix = $previousGroupPrefix . $prefix;
|
||||
$callback($this);
|
||||
$this->currentGroupPrefix = $previousGroupPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GET route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('GET', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function get($route, $handler)
|
||||
{
|
||||
$this->addRoute('GET', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a POST route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('POST', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function post($route, $handler)
|
||||
{
|
||||
$this->addRoute('POST', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PUT route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('PUT', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function put($route, $handler)
|
||||
{
|
||||
$this->addRoute('PUT', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DELETE route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('DELETE', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function delete($route, $handler)
|
||||
{
|
||||
$this->addRoute('DELETE', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PATCH route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('PATCH', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function patch($route, $handler)
|
||||
{
|
||||
$this->addRoute('PATCH', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a HEAD route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('HEAD', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function head($route, $handler)
|
||||
{
|
||||
$this->addRoute('HEAD', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collected route data, as provided by the data generator.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->dataGenerator->getData();
|
||||
}
|
||||
}
|
37
vendor/nikic/fast-route/src/RouteParser.php
vendored
Normal file
37
vendor/nikic/fast-route/src/RouteParser.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface RouteParser
|
||||
{
|
||||
/**
|
||||
* Parses a route string into multiple route data arrays.
|
||||
*
|
||||
* The expected output is defined using an example:
|
||||
*
|
||||
* For the route string "/fixedRoutePart/{varName}[/moreFixed/{varName2:\d+}]", if {varName} is interpreted as
|
||||
* a placeholder and [...] is interpreted as an optional route part, the expected result is:
|
||||
*
|
||||
* [
|
||||
* // first route: without optional part
|
||||
* [
|
||||
* "/fixedRoutePart/",
|
||||
* ["varName", "[^/]+"],
|
||||
* ],
|
||||
* // second route: with optional part
|
||||
* [
|
||||
* "/fixedRoutePart/",
|
||||
* ["varName", "[^/]+"],
|
||||
* "/moreFixed/",
|
||||
* ["varName2", [0-9]+"],
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* Here one route string was converted into two route data arrays.
|
||||
*
|
||||
* @param string $route Route string to parse
|
||||
*
|
||||
* @return mixed[][] Array of route data arrays
|
||||
*/
|
||||
public function parse($route);
|
||||
}
|
87
vendor/nikic/fast-route/src/RouteParser/Std.php
vendored
Normal file
87
vendor/nikic/fast-route/src/RouteParser/Std.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\RouteParser;
|
||||
|
||||
use FastRoute\BadRouteException;
|
||||
use FastRoute\RouteParser;
|
||||
|
||||
/**
|
||||
* Parses route strings of the following form:
|
||||
*
|
||||
* "/user/{name}[/{id:[0-9]+}]"
|
||||
*/
|
||||
class Std implements RouteParser
|
||||
{
|
||||
const VARIABLE_REGEX = <<<'REGEX'
|
||||
\{
|
||||
\s* ([a-zA-Z_][a-zA-Z0-9_-]*) \s*
|
||||
(?:
|
||||
: \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
|
||||
)?
|
||||
\}
|
||||
REGEX;
|
||||
const DEFAULT_DISPATCH_REGEX = '[^/]+';
|
||||
|
||||
public function parse($route)
|
||||
{
|
||||
$routeWithoutClosingOptionals = rtrim($route, ']');
|
||||
$numOptionals = strlen($route) - strlen($routeWithoutClosingOptionals);
|
||||
|
||||
// Split on [ while skipping placeholders
|
||||
$segments = preg_split('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \[~x', $routeWithoutClosingOptionals);
|
||||
if ($numOptionals !== count($segments) - 1) {
|
||||
// If there are any ] in the middle of the route, throw a more specific error message
|
||||
if (preg_match('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \]~x', $routeWithoutClosingOptionals)) {
|
||||
throw new BadRouteException('Optional segments can only occur at the end of a route');
|
||||
}
|
||||
throw new BadRouteException("Number of opening '[' and closing ']' does not match");
|
||||
}
|
||||
|
||||
$currentRoute = '';
|
||||
$routeDatas = [];
|
||||
foreach ($segments as $n => $segment) {
|
||||
if ($segment === '' && $n !== 0) {
|
||||
throw new BadRouteException('Empty optional part');
|
||||
}
|
||||
|
||||
$currentRoute .= $segment;
|
||||
$routeDatas[] = $this->parsePlaceholders($currentRoute);
|
||||
}
|
||||
return $routeDatas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a route string that does not contain optional segments.
|
||||
*
|
||||
* @param string
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function parsePlaceholders($route)
|
||||
{
|
||||
if (!preg_match_all(
|
||||
'~' . self::VARIABLE_REGEX . '~x', $route, $matches,
|
||||
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
||||
)) {
|
||||
return [$route];
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
$routeData = [];
|
||||
foreach ($matches as $set) {
|
||||
if ($set[0][1] > $offset) {
|
||||
$routeData[] = substr($route, $offset, $set[0][1] - $offset);
|
||||
}
|
||||
$routeData[] = [
|
||||
$set[1][0],
|
||||
isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX
|
||||
];
|
||||
$offset = $set[0][1] + strlen($set[0][0]);
|
||||
}
|
||||
|
||||
if ($offset !== strlen($route)) {
|
||||
$routeData[] = substr($route, $offset);
|
||||
}
|
||||
|
||||
return $routeData;
|
||||
}
|
||||
}
|
12
vendor/nikic/fast-route/src/bootstrap.php
vendored
Normal file
12
vendor/nikic/fast-route/src/bootstrap.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
require __DIR__ . '/functions.php';
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
if (strpos($class, 'FastRoute\\') === 0) {
|
||||
$name = substr($class, strlen('FastRoute'));
|
||||
require __DIR__ . strtr($name, '\\', DIRECTORY_SEPARATOR) . '.php';
|
||||
}
|
||||
});
|
74
vendor/nikic/fast-route/src/functions.php
vendored
Normal file
74
vendor/nikic/fast-route/src/functions.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
if (!function_exists('FastRoute\simpleDispatcher')) {
|
||||
/**
|
||||
* @param callable $routeDefinitionCallback
|
||||
* @param array $options
|
||||
*
|
||||
* @return Dispatcher
|
||||
*/
|
||||
function simpleDispatcher(callable $routeDefinitionCallback, array $options = [])
|
||||
{
|
||||
$options += [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
'routeCollector' => 'FastRoute\\RouteCollector',
|
||||
];
|
||||
|
||||
/** @var RouteCollector $routeCollector */
|
||||
$routeCollector = new $options['routeCollector'](
|
||||
new $options['routeParser'], new $options['dataGenerator']
|
||||
);
|
||||
$routeDefinitionCallback($routeCollector);
|
||||
|
||||
return new $options['dispatcher']($routeCollector->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $routeDefinitionCallback
|
||||
* @param array $options
|
||||
*
|
||||
* @return Dispatcher
|
||||
*/
|
||||
function cachedDispatcher(callable $routeDefinitionCallback, array $options = [])
|
||||
{
|
||||
$options += [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
'routeCollector' => 'FastRoute\\RouteCollector',
|
||||
'cacheDisabled' => false,
|
||||
];
|
||||
|
||||
if (!isset($options['cacheFile'])) {
|
||||
throw new \LogicException('Must specify "cacheFile" option');
|
||||
}
|
||||
|
||||
if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) {
|
||||
$dispatchData = require $options['cacheFile'];
|
||||
if (!is_array($dispatchData)) {
|
||||
throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"');
|
||||
}
|
||||
return new $options['dispatcher']($dispatchData);
|
||||
}
|
||||
|
||||
$routeCollector = new $options['routeCollector'](
|
||||
new $options['routeParser'], new $options['dataGenerator']
|
||||
);
|
||||
$routeDefinitionCallback($routeCollector);
|
||||
|
||||
/** @var RouteCollector $routeCollector */
|
||||
$dispatchData = $routeCollector->getData();
|
||||
if (!$options['cacheDisabled']) {
|
||||
file_put_contents(
|
||||
$options['cacheFile'],
|
||||
'<?php return ' . var_export($dispatchData, true) . ';'
|
||||
);
|
||||
}
|
||||
|
||||
return new $options['dispatcher']($dispatchData);
|
||||
}
|
||||
}
|
16
vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php
vendored
Normal file
16
vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class CharCountBasedTest extends DispatcherTest
|
||||
{
|
||||
protected function getDispatcherClass()
|
||||
{
|
||||
return 'FastRoute\\Dispatcher\\CharCountBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass()
|
||||
{
|
||||
return 'FastRoute\\DataGenerator\\CharCountBased';
|
||||
}
|
||||
}
|
581
vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php
vendored
Normal file
581
vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
use FastRoute\RouteCollector;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
abstract class DispatcherTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Delegate dispatcher selection to child test classes
|
||||
*/
|
||||
abstract protected function getDispatcherClass();
|
||||
|
||||
/**
|
||||
* Delegate dataGenerator selection to child test classes
|
||||
*/
|
||||
abstract protected function getDataGeneratorClass();
|
||||
|
||||
/**
|
||||
* Set appropriate options for the specific Dispatcher class we're testing
|
||||
*/
|
||||
private function generateDispatcherOptions()
|
||||
{
|
||||
return [
|
||||
'dataGenerator' => $this->getDataGeneratorClass(),
|
||||
'dispatcher' => $this->getDispatcherClass()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFoundDispatchCases
|
||||
*/
|
||||
public function testFoundDispatches($method, $uri, $callback, $handler, $argDict)
|
||||
{
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$info = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertSame($dispatcher::FOUND, $info[0]);
|
||||
$this->assertSame($handler, $info[1]);
|
||||
$this->assertSame($argDict, $info[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideNotFoundDispatchCases
|
||||
*/
|
||||
public function testNotFoundDispatches($method, $uri, $callback)
|
||||
{
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$routeInfo = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertArrayNotHasKey(1, $routeInfo,
|
||||
'NOT_FOUND result must only contain a single element in the returned info array'
|
||||
);
|
||||
$this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMethodNotAllowedDispatchCases
|
||||
*/
|
||||
public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods)
|
||||
{
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$routeInfo = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertArrayHasKey(1, $routeInfo,
|
||||
'METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1'
|
||||
);
|
||||
|
||||
list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus);
|
||||
$this->assertSame($availableMethods, $methodArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot use the same placeholder "test" twice
|
||||
*/
|
||||
public function testDuplicateVariableNameError()
|
||||
{
|
||||
\FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET"
|
||||
*/
|
||||
public function testDuplicateVariableRoute()
|
||||
{
|
||||
\FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;)
|
||||
$r->addRoute('GET', '/user/{name}', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET"
|
||||
*/
|
||||
public function testDuplicateStaticRoute()
|
||||
{
|
||||
\FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user', 'handler0');
|
||||
$r->addRoute('GET', '/user', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET"
|
||||
*/
|
||||
public function testShadowedStaticRoute()
|
||||
{
|
||||
\FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/nikic', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group
|
||||
*/
|
||||
public function testCapturing()
|
||||
{
|
||||
\FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/{lang:(en|de)}', 'handler0');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
public function provideFoundDispatchCases()
|
||||
{
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/resource/123/456';
|
||||
$handler = 'handler0';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/handler0', 'handler0');
|
||||
$r->addRoute('GET', '/handler1', 'handler1');
|
||||
$r->addRoute('GET', '/handler2', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/handler2';
|
||||
$handler = 'handler2';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #2
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/12345';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['id' => '12345'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #3
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/NaN';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['name' => 'NaN'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 5 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #4
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/12345';
|
||||
$handler = 'handler0';
|
||||
$argDict = ['name' => 'rdlowrey', 'id' => '12345'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 6 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/12345/extension', 'handler1');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/12345.svg';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['id' => '12345', 'extension' => 'svg'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 7 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/static0', 'handler2');
|
||||
$r->addRoute('GET', '/static1', 'handler3');
|
||||
$r->addRoute('HEAD', '/static1', 'handler4');
|
||||
};
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler0';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 8 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
// reuse $callback from #7
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/user/rdlowrey/1234';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey', 'id' => '1234'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 9 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
// reuse $callback from #8
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/static0';
|
||||
$handler = 'handler2';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 10 ---- Test existing HEAD route used if available (no fallback) ----------------------->
|
||||
|
||||
// reuse $callback from #9
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/static1';
|
||||
$handler = 'handler4';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 11 ---- More specified routes are not shadowed by less specific of another method ------>
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 12 ---- Handler of more specific routes is used, if it occurs first -------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1');
|
||||
$r->addRoute('POST', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 13 ---- Route with constant suffix ----------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{name}/edit', 'handler1');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/edit';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 14 ---- Handle multiple methods with the same handler ---------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost');
|
||||
$r->addRoute(['DELETE'], '/user', 'handlerDelete');
|
||||
$r->addRoute([], '/user', 'handlerNone');
|
||||
};
|
||||
|
||||
$argDict = [];
|
||||
$cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict];
|
||||
$cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict];
|
||||
$cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict];
|
||||
|
||||
// 17 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user.json', 'handler0');
|
||||
$r->addRoute('GET', '/{entity}.json', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']];
|
||||
|
||||
// 18 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '', 'handler0');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '', $callback, 'handler0', []];
|
||||
|
||||
// 19 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('HEAD', '/a/{foo}', 'handler0');
|
||||
$r->addRoute('GET', '/b/{foo}', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']];
|
||||
|
||||
// 20 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('HEAD', '/a', 'handler0');
|
||||
$r->addRoute('GET', '/b', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/b', $callback, 'handler1', []];
|
||||
|
||||
// 21 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/foo', 'handler0');
|
||||
$r->addRoute('HEAD', '/{bar}', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']];
|
||||
|
||||
// 22 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('*', '/user', 'handler0');
|
||||
$r->addRoute('*', '/{user}', 'handler1');
|
||||
$r->addRoute('GET', '/user', 'handler2');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/user', $callback, 'handler2', []];
|
||||
|
||||
// 23 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('*', '/user', 'handler0');
|
||||
$r->addRoute('GET', '/user', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['POST', '/user', $callback, 'handler0', []];
|
||||
|
||||
// 24 ----
|
||||
|
||||
$cases[] = ['HEAD', '/user', $callback, 'handler1', []];
|
||||
|
||||
// 25 ----
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/{bar}', 'handler0');
|
||||
$r->addRoute('*', '/foo', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']];
|
||||
|
||||
// 26 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user', 'handler0');
|
||||
$r->addRoute('*', '/{foo:.*}', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['POST', '/bar', $callback, 'handler1', ['foo' => 'bar']];
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
public function provideNotFoundDispatchCases()
|
||||
{
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #0
|
||||
$method = 'POST';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #1
|
||||
$method = 'PUT';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/handler0', 'handler0');
|
||||
$r->addRoute('GET', '/handler1', 'handler1');
|
||||
$r->addRoute('GET', '/handler2', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 5 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #4
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/12345/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 6 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #5
|
||||
$method = 'HEAD';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
public function provideMethodNotAllowedDispatchCases()
|
||||
{
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/resource/123/456';
|
||||
$allowedMethods = ['GET'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
$r->addRoute('POST', '/resource/123/456', 'handler1');
|
||||
$r->addRoute('PUT', '/resource/123/456', 'handler2');
|
||||
$r->addRoute('*', '/', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'DELETE';
|
||||
$uri = '/resource/123/456';
|
||||
$allowedMethods = ['GET', 'POST', 'PUT'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2');
|
||||
$r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'DELETE';
|
||||
$uri = '/user/rdlowrey/42';
|
||||
$allowedMethods = ['GET', 'POST', 'PUT', 'PATCH'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user/{name}', 'handler1');
|
||||
$r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2');
|
||||
$r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey';
|
||||
$allowedMethods = ['POST', 'PUT', 'PATCH'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost');
|
||||
$r->addRoute(['DELETE'], '/user', 'handlerDelete');
|
||||
$r->addRoute([], '/user', 'handlerNone');
|
||||
};
|
||||
|
||||
$cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']];
|
||||
|
||||
// 5
|
||||
|
||||
$callback = function (RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user.json', 'handler0');
|
||||
$r->addRoute('GET', '/{entity}.json', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']];
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
}
|
16
vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php
vendored
Normal file
16
vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupCountBasedTest extends DispatcherTest
|
||||
{
|
||||
protected function getDispatcherClass()
|
||||
{
|
||||
return 'FastRoute\\Dispatcher\\GroupCountBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass()
|
||||
{
|
||||
return 'FastRoute\\DataGenerator\\GroupCountBased';
|
||||
}
|
||||
}
|
16
vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php
vendored
Normal file
16
vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupPosBasedTest extends DispatcherTest
|
||||
{
|
||||
protected function getDispatcherClass()
|
||||
{
|
||||
return 'FastRoute\\Dispatcher\\GroupPosBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass()
|
||||
{
|
||||
return 'FastRoute\\DataGenerator\\GroupPosBased';
|
||||
}
|
||||
}
|
24
vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php
vendored
Normal file
24
vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class MarkBasedTest extends DispatcherTest
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
preg_match('/(*MARK:A)a/', 'a', $matches);
|
||||
if (!isset($matches['MARK'])) {
|
||||
$this->markTestSkipped('PHP 5.6 required for MARK support');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getDispatcherClass()
|
||||
{
|
||||
return 'FastRoute\\Dispatcher\\MarkBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass()
|
||||
{
|
||||
return 'FastRoute\\DataGenerator\\MarkBased';
|
||||
}
|
||||
}
|
44
vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php
vendored
Normal file
44
vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class HackTypecheckerTest extends TestCase
|
||||
{
|
||||
const SERVER_ALREADY_RUNNING_CODE = 77;
|
||||
|
||||
public function testTypechecks($recurse = true)
|
||||
{
|
||||
if (!defined('HHVM_VERSION')) {
|
||||
$this->markTestSkipped('HHVM only');
|
||||
}
|
||||
if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) {
|
||||
$this->markTestSkipped('classname<T> requires HHVM 3.9+');
|
||||
}
|
||||
|
||||
// The typechecker recurses the whole tree, so it makes sure
|
||||
// that everything in fixtures/ is valid when this runs.
|
||||
|
||||
$output = [];
|
||||
$exit_code = null;
|
||||
exec(
|
||||
'hh_server --check ' . escapeshellarg(__DIR__ . '/../../') . ' 2>&1',
|
||||
$output,
|
||||
$exit_code
|
||||
);
|
||||
if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) {
|
||||
$this->assertTrue(
|
||||
$recurse,
|
||||
'Typechecker still running after running hh_client stop'
|
||||
);
|
||||
// Server already running - 3.10 => 3.11 regression:
|
||||
// https://github.com/facebook/hhvm/issues/6646
|
||||
exec('hh_client stop 2>/dev/null');
|
||||
$this->testTypechecks(/* recurse = */ false);
|
||||
return;
|
||||
|
||||
}
|
||||
$this->assertSame(0, $exit_code, implode("\n", $output));
|
||||
}
|
||||
}
|
29
vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php
vendored
Normal file
29
vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function all_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher(
|
||||
$collector ==> {},
|
||||
shape(
|
||||
'routeParser' => \FastRoute\RouteParser\Std::class,
|
||||
'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class,
|
||||
'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class,
|
||||
'routeCollector' => \FastRoute\RouteCollector::class,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function all_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher(
|
||||
$collector ==> {},
|
||||
shape(
|
||||
'routeParser' => \FastRoute\RouteParser\Std::class,
|
||||
'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class,
|
||||
'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class,
|
||||
'routeCollector' => \FastRoute\RouteCollector::class,
|
||||
'cacheFile' => '/dev/null',
|
||||
'cacheDisabled' => false,
|
||||
),
|
||||
);
|
||||
}
|
11
vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php
vendored
Normal file
11
vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function empty_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher($collector ==> {}, shape());
|
||||
}
|
||||
|
||||
function empty_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher($collector ==> {}, shape());
|
||||
}
|
11
vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php
vendored
Normal file
11
vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function no_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher($collector ==> {});
|
||||
}
|
||||
|
||||
function no_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher($collector ==> {});
|
||||
}
|
108
vendor/nikic/fast-route/test/RouteCollectorTest.php
vendored
Normal file
108
vendor/nikic/fast-route/test/RouteCollectorTest.php
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class RouteCollectorTest extends TestCase
|
||||
{
|
||||
public function testShortcuts()
|
||||
{
|
||||
$r = new DummyRouteCollector();
|
||||
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$expected = [
|
||||
['DELETE', '/delete', 'delete'],
|
||||
['GET', '/get', 'get'],
|
||||
['HEAD', '/head', 'head'],
|
||||
['PATCH', '/patch', 'patch'],
|
||||
['POST', '/post', 'post'],
|
||||
['PUT', '/put', 'put'],
|
||||
];
|
||||
|
||||
$this->assertSame($expected, $r->routes);
|
||||
}
|
||||
|
||||
public function testGroups()
|
||||
{
|
||||
$r = new DummyRouteCollector();
|
||||
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$r->addGroup('/group-one', function (DummyRouteCollector $r) {
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$r->addGroup('/group-two', function (DummyRouteCollector $r) {
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
});
|
||||
});
|
||||
|
||||
$r->addGroup('/admin', function (DummyRouteCollector $r) {
|
||||
$r->get('-some-info', 'admin-some-info');
|
||||
});
|
||||
$r->addGroup('/admin-', function (DummyRouteCollector $r) {
|
||||
$r->get('more-info', 'admin-more-info');
|
||||
});
|
||||
|
||||
$expected = [
|
||||
['DELETE', '/delete', 'delete'],
|
||||
['GET', '/get', 'get'],
|
||||
['HEAD', '/head', 'head'],
|
||||
['PATCH', '/patch', 'patch'],
|
||||
['POST', '/post', 'post'],
|
||||
['PUT', '/put', 'put'],
|
||||
['DELETE', '/group-one/delete', 'delete'],
|
||||
['GET', '/group-one/get', 'get'],
|
||||
['HEAD', '/group-one/head', 'head'],
|
||||
['PATCH', '/group-one/patch', 'patch'],
|
||||
['POST', '/group-one/post', 'post'],
|
||||
['PUT', '/group-one/put', 'put'],
|
||||
['DELETE', '/group-one/group-two/delete', 'delete'],
|
||||
['GET', '/group-one/group-two/get', 'get'],
|
||||
['HEAD', '/group-one/group-two/head', 'head'],
|
||||
['PATCH', '/group-one/group-two/patch', 'patch'],
|
||||
['POST', '/group-one/group-two/post', 'post'],
|
||||
['PUT', '/group-one/group-two/put', 'put'],
|
||||
['GET', '/admin-some-info', 'admin-some-info'],
|
||||
['GET', '/admin-more-info', 'admin-more-info'],
|
||||
];
|
||||
|
||||
$this->assertSame($expected, $r->routes);
|
||||
}
|
||||
}
|
||||
|
||||
class DummyRouteCollector extends RouteCollector
|
||||
{
|
||||
public $routes = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function addRoute($method, $route, $handler)
|
||||
{
|
||||
$route = $this->currentGroupPrefix . $route;
|
||||
$this->routes[] = [$method, $route, $handler];
|
||||
}
|
||||
}
|
154
vendor/nikic/fast-route/test/RouteParser/StdTest.php
vendored
Normal file
154
vendor/nikic/fast-route/test/RouteParser/StdTest.php
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\RouteParser;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class StdTest extends TestCase
|
||||
{
|
||||
/** @dataProvider provideTestParse */
|
||||
public function testParse($routeString, $expectedRouteDatas)
|
||||
{
|
||||
$parser = new Std();
|
||||
$routeDatas = $parser->parse($routeString);
|
||||
$this->assertSame($expectedRouteDatas, $routeDatas);
|
||||
}
|
||||
|
||||
/** @dataProvider provideTestParseError */
|
||||
public function testParseError($routeString, $expectedExceptionMessage)
|
||||
{
|
||||
$parser = new Std();
|
||||
$this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage);
|
||||
$parser->parse($routeString);
|
||||
}
|
||||
|
||||
public function provideTestParse()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'/test',
|
||||
[
|
||||
['/test'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param}',
|
||||
[
|
||||
['/test/', ['param', '[^/]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/te{ param }st',
|
||||
[
|
||||
['/te', ['param', '[^/]+'], 'st']
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param1}/test2/{param2}',
|
||||
[
|
||||
['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param:\d+}',
|
||||
[
|
||||
['/test/', ['param', '\d+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{ param : \d{1,9} }',
|
||||
[
|
||||
['/test/', ['param', '\d{1,9}']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[opt]',
|
||||
[
|
||||
['/test'],
|
||||
['/testopt'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[/{param}]',
|
||||
[
|
||||
['/test'],
|
||||
['/test/', ['param', '[^/]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{param}[opt]',
|
||||
[
|
||||
['/', ['param', '[^/]+']],
|
||||
['/', ['param', '[^/]+'], 'opt']
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[/{name}[/{id:[0-9]+}]]',
|
||||
[
|
||||
['/test'],
|
||||
['/test/', ['name', '[^/]+']],
|
||||
['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'',
|
||||
[
|
||||
[''],
|
||||
]
|
||||
],
|
||||
[
|
||||
'[test]',
|
||||
[
|
||||
[''],
|
||||
['test'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{foo-bar}',
|
||||
[
|
||||
['/', ['foo-bar', '[^/]+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{_foo:.*}',
|
||||
[
|
||||
['/', ['_foo', '.*']]
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function provideTestParseError()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'/test[opt',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/test[opt[opt2]',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/testopt]',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/test[]',
|
||||
'Empty optional part'
|
||||
],
|
||||
[
|
||||
'/test[[opt]]',
|
||||
'Empty optional part'
|
||||
],
|
||||
[
|
||||
'[[test]]',
|
||||
'Empty optional part'
|
||||
],
|
||||
[
|
||||
'/test[/opt]/required',
|
||||
'Optional segments can only occur at the end of a route'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
11
vendor/nikic/fast-route/test/bootstrap.php
vendored
Normal file
11
vendor/nikic/fast-route/test/bootstrap.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../src/functions.php';
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
if (strpos($class, 'FastRoute\\') === 0) {
|
||||
$dir = strcasecmp(substr($class, -4), 'Test') ? 'src/' : 'test/';
|
||||
$name = substr($class, strlen('FastRoute'));
|
||||
require __DIR__ . '/../' . $dir . strtr($name, '\\', DIRECTORY_SEPARATOR) . '.php';
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user