mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-21 18:51:26 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29ab0e85ae | |||
| 539e905b45 | |||
| 0ab15839a9 | |||
| 5977efc942 |
@@ -1,22 +0,0 @@
|
||||
engines:
|
||||
phpmd:
|
||||
enabled: true
|
||||
checks:
|
||||
Design/TooManyPublicMethods:
|
||||
enabled: true
|
||||
Naming/ShortVariable:
|
||||
enabled: true
|
||||
CleanCode/StaticAccess:
|
||||
enabled: true
|
||||
Controversial/CamelCaseMethodName:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- php:
|
||||
ratings:
|
||||
paths:
|
||||
- src/**
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
.idea
|
||||
composer.lock
|
||||
vendor/
|
||||
vendor/
|
||||
demo-project/vendor
|
||||
@@ -1,13 +0,0 @@
|
||||
build:
|
||||
tests:
|
||||
override:
|
||||
-
|
||||
command: './vendor/bin/phpunit --coverage-clover=coverage.clover'
|
||||
coverage:
|
||||
file: 'coverage.clover'
|
||||
format: 'clover'
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
duplication: true
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 7.1
|
||||
|
||||
before_script:
|
||||
- curl -sS http://getcomposer.org/installer | php
|
||||
- php composer.phar install --prefer-source --no-interaction
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpunit
|
||||
+23
-38
@@ -1,41 +1,26 @@
|
||||
{
|
||||
"name": "pecee/simple-router",
|
||||
"description": "Simple, fast PHP router that is easy to get integrated and in almost any project. Heavily inspired by the Laravel router.",
|
||||
"keywords": [
|
||||
"router",
|
||||
"router",
|
||||
"routing",
|
||||
"route",
|
||||
"simple-php-router",
|
||||
"laravel",
|
||||
"pecee",
|
||||
"php",
|
||||
"framework",
|
||||
"url-handling",
|
||||
"input-handler",
|
||||
"routing-engine",
|
||||
"request-handler"
|
||||
],
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"source": "https://github.com/skipperbent/simple-php-router/issues"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Sessingø",
|
||||
"email": "simon.sessingoe@gmail.com"
|
||||
"name": "pecee/simple-router",
|
||||
"description": "Simple, fast PHP router that is easy to get integrated and in almost any project. Heavily inspired by the Laravel router.",
|
||||
"keywords": [ "router", "routing", "laravel", "pecee" ],
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"source": "https://github.com/skipperbent/simple-php-router/issues"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Sessingø",
|
||||
"email": "simon.sessingoe@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.7.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Pecee\\": "src/Pecee/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.0",
|
||||
"mockery/mockery": "^1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Pecee\\": "src/Pecee/"
|
||||
}
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Pecee\SimpleRouter\SimpleRouter as Router;
|
||||
|
||||
/**
|
||||
* Get url for a route by using either name/alias, class or method name.
|
||||
*
|
||||
* The name parameter supports the following values:
|
||||
* - Route name
|
||||
* - Controller/resource name (with or without method)
|
||||
* - Controller class name
|
||||
*
|
||||
* When searching for controller/resource by name, you can use this syntax "route.name@method".
|
||||
* You can also use the same syntax when searching for a specific controller-class "MyController@home".
|
||||
* If no arguments is specified, it will return the url for the current loaded route.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|array|null $parameters
|
||||
* @param array|null $getParams
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
function url($name = null, $parameters = null, $getParams = null)
|
||||
{
|
||||
return Router::getUrl($name, $parameters, $getParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pecee\Http\Response
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
function response()
|
||||
{
|
||||
return Router::response();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pecee\Http\Request
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return Router::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input class
|
||||
* @param string|null $index Parameter index name
|
||||
* @param string|null $defaultValue Default return value
|
||||
* @param string|array|null $methods Default method
|
||||
* @return \Pecee\Http\Input\InputHandler|string
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
function input($index = null, $defaultValue = null, $methods = null)
|
||||
{
|
||||
if ($index !== null) {
|
||||
return request()->getInputHandler()->get($index, $defaultValue, $methods);
|
||||
}
|
||||
|
||||
return request()->getInputHandler();
|
||||
}
|
||||
|
||||
function redirect($url, $code = null)
|
||||
{
|
||||
if ($code !== null) {
|
||||
response()->httpCode($code);
|
||||
}
|
||||
|
||||
response()->redirect($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current csrf-token
|
||||
* @return string|null
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
function csrf_token()
|
||||
{
|
||||
$baseVerifier = Router::router()->getCsrfVerifier();
|
||||
if ($baseVerifier !== null) {
|
||||
return $baseVerifier->getTokenProvider()->getToken();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false">
|
||||
<testsuites>
|
||||
<testsuite name="SimpleRouter Test Suite">
|
||||
<directory>tests/Pecee/SimpleRouter/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Controllers;
|
||||
|
||||
interface IResourceController
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function index(): ?string;
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return string|null
|
||||
*/
|
||||
public function show($id): ?string;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function store(): ?string;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function create(): ?string;
|
||||
|
||||
/**
|
||||
* View
|
||||
* @param mixed $id
|
||||
* @return string|null
|
||||
*/
|
||||
public function edit($id): ?string;
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return string|null
|
||||
*/
|
||||
public function update($id): ?string;
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return string|null
|
||||
*/
|
||||
public function destroy($id): ?string;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Pecee\Controllers;
|
||||
|
||||
interface IRestController
|
||||
{
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index();
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return void
|
||||
*/
|
||||
public function show($id);
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function store();
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function create();
|
||||
|
||||
/**
|
||||
* View
|
||||
* @param mixed $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id);
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return void
|
||||
*/
|
||||
public function update($id);
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return void
|
||||
*/
|
||||
public function destroy($id);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace Pecee;
|
||||
|
||||
class CsrfToken
|
||||
{
|
||||
const CSRF_KEY = 'XSRF-TOKEN';
|
||||
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* Generate random identifier for CSRF token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateToken()
|
||||
{
|
||||
if (function_exists('random_bytes')) {
|
||||
return bin2hex(random_bytes(32));
|
||||
}
|
||||
|
||||
return bin2hex(openssl_random_pseudo_bytes(32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate valid CSRF token
|
||||
*
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($token)
|
||||
{
|
||||
if ($token !== null && $this->getToken() !== null) {
|
||||
return hash_equals($token, $this->getToken());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set csrf token cookie
|
||||
*
|
||||
* @param $token
|
||||
*/
|
||||
public function setToken($token)
|
||||
{
|
||||
setcookie(static::CSRF_KEY, $token, time() + 60 * 120, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get csrf token
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
if ($this->hasToken()) {
|
||||
return $_COOKIE[static::CSRF_KEY];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the csrf token has been defined
|
||||
* @return bool
|
||||
*/
|
||||
public function hasToken()
|
||||
{
|
||||
return isset($_COOKIE[static::CSRF_KEY]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Exceptions;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Handlers;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
|
||||
/**
|
||||
* Class CallbackExceptionHandler
|
||||
*
|
||||
* Class is used to create callbacks which are fired when an exception is reached.
|
||||
* This allows for easy handling 404-exception etc. without creating an custom ExceptionHandler.
|
||||
*
|
||||
* @package Pecee\Handlers
|
||||
*/
|
||||
class CallbackExceptionHandler implements IExceptionHandler
|
||||
{
|
||||
|
||||
protected $callback;
|
||||
|
||||
public function __construct(\Closure $callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param \Exception $error
|
||||
*/
|
||||
public function handleError(Request $request, \Exception $error): void
|
||||
{
|
||||
/* Fire exceptions */
|
||||
\call_user_func($this->callback,
|
||||
$request,
|
||||
$error
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Handlers;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
interface IExceptionHandler
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ILoadableRoute $route
|
||||
* @param \Exception $error
|
||||
* @return Request|null
|
||||
*/
|
||||
public function handleError(Request $request, \Exception $error): void;
|
||||
public function handleError(Request $request, ILoadableRoute &$route = null, \Exception $error);
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Exceptions;
|
||||
|
||||
class MalformedUrlException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,21 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
interface IInputItem
|
||||
{
|
||||
|
||||
public function getIndex(): string;
|
||||
public function getIndex();
|
||||
|
||||
public function setIndex(string $index): self;
|
||||
public function setIndex($index);
|
||||
|
||||
public function getName(): string;
|
||||
public function getName();
|
||||
|
||||
public function setName(string $name): self;
|
||||
|
||||
public function getValue(): string;
|
||||
|
||||
public function setValue(string $value): self;
|
||||
public function setName($name);
|
||||
|
||||
public function __toString();
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
use Pecee\Exceptions\InvalidArgumentException;
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class InputHandler
|
||||
class Input
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
@@ -27,10 +25,6 @@ class InputHandler
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Input constructor.
|
||||
* @param Request $request
|
||||
*/
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
@@ -38,59 +32,48 @@ class InputHandler
|
||||
$this->parseInputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse input values
|
||||
*
|
||||
*/
|
||||
public function parseInputs(): void
|
||||
public function parseInputs()
|
||||
{
|
||||
/* Parse get requests */
|
||||
if (\count($_GET) !== 0) {
|
||||
if (count($_GET) > 0) {
|
||||
$this->get = $this->handleGetPost($_GET);
|
||||
}
|
||||
|
||||
/* Parse post requests */
|
||||
$postVars = $_POST;
|
||||
|
||||
if (\in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) {
|
||||
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) {
|
||||
parse_str(file_get_contents('php://input'), $postVars);
|
||||
}
|
||||
|
||||
if (\count($postVars) !== 0) {
|
||||
if (count($postVars) > 0) {
|
||||
$this->post = $this->handleGetPost($postVars);
|
||||
}
|
||||
|
||||
/* Parse get requests */
|
||||
if (\count($_FILES) !== 0) {
|
||||
if (count($_FILES) > 0) {
|
||||
$this->file = $this->parseFiles();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function parseFiles(): array
|
||||
public function parseFiles()
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ((array)$_FILES as $key => $value) {
|
||||
foreach ($_FILES as $key => $value) {
|
||||
|
||||
// Handle array input
|
||||
if (\is_array($value['name']) === false) {
|
||||
if (is_array($value['name']) === false) {
|
||||
$values['index'] = $key;
|
||||
try {
|
||||
$list[$key] = InputFile::createFromArray($values + $value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
|
||||
}
|
||||
$list[$key] = InputFile::createFromArray(array_merge($value, $values));
|
||||
continue;
|
||||
}
|
||||
|
||||
$keys = [$key];
|
||||
$keys = [];
|
||||
|
||||
$files = $this->rearrangeFiles($value['name'], $keys, $value);
|
||||
|
||||
if (isset($list[$key]) === true) {
|
||||
if (isset($list[$key])) {
|
||||
$list[$key][] = $files;
|
||||
} else {
|
||||
$list[$key] = $files;
|
||||
@@ -101,47 +84,49 @@ class InputHandler
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function rearrangeFiles(array $values, &$index, $original): array
|
||||
protected function rearrangeFiles(array $values, &$index, $original)
|
||||
{
|
||||
|
||||
$originalIndex = $index[0];
|
||||
array_shift($index);
|
||||
|
||||
$output = [];
|
||||
|
||||
$getItem = function ($key, $property = 'name') use ($original, $index) {
|
||||
|
||||
$path = $original[$property];
|
||||
|
||||
foreach (array_values($index) as $i) {
|
||||
$path = $path[$i];
|
||||
}
|
||||
|
||||
return $path[$key];
|
||||
};
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
|
||||
if (\is_array($original['name'][$key]) === false) {
|
||||
if (is_array($getItem($key)) === false) {
|
||||
|
||||
try {
|
||||
|
||||
$file = InputFile::createFromArray([
|
||||
'index' => (empty($key) === true && empty($originalIndex) === false) ? $originalIndex : $key,
|
||||
'name' => $original['name'][$key],
|
||||
'error' => $original['error'][$key],
|
||||
'tmp_name' => $original['tmp_name'][$key],
|
||||
'type' => $original['type'][$key],
|
||||
'size' => $original['size'][$key],
|
||||
]);
|
||||
|
||||
if (isset($output[$key]) === true) {
|
||||
$output[$key][] = $file;
|
||||
continue;
|
||||
}
|
||||
$file = InputFile::createFromArray([
|
||||
'index' => $key,
|
||||
'error' => $getItem($key, 'error'),
|
||||
'tmp_name' => $getItem($key, 'tmp_name'),
|
||||
'type' => $getItem($key, 'type'),
|
||||
'size' => $getItem($key, 'size'),
|
||||
'filename' => $getItem($key, 'name'),
|
||||
]);
|
||||
|
||||
if (isset($output[$key])) {
|
||||
$output[$key][] = $file;
|
||||
} else {
|
||||
$output[$key] = $file;
|
||||
continue;
|
||||
|
||||
} catch (InvalidArgumentException $e) {
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$index[] = $key;
|
||||
|
||||
$files = $this->rearrangeFiles($value, $index, $original);
|
||||
|
||||
if (isset($output[$key]) === true) {
|
||||
if (isset($output[$key])) {
|
||||
$output[$key][] = $files;
|
||||
} else {
|
||||
$output[$key] = $files;
|
||||
@@ -152,14 +137,20 @@ class InputHandler
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function handleGetPost(array $array): array
|
||||
protected function handleGetPost(array $array)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
$max = count($array) - 1;
|
||||
$keys = array_keys($array);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$key = $keys[$i];
|
||||
$value = $array[$key];
|
||||
|
||||
// Handle array input
|
||||
if (\is_array($value) === false) {
|
||||
if (is_array($value) === false) {
|
||||
$list[$key] = new InputItem($key, $value);
|
||||
continue;
|
||||
}
|
||||
@@ -179,9 +170,9 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function findPost(string $index, ?string $defaultValue = null)
|
||||
public function findPost($index, $defaultValue = null)
|
||||
{
|
||||
return $this->post[$index] ?? $defaultValue;
|
||||
return isset($this->post[$index]) ? $this->post[$index] : $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,9 +182,9 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputFile|string
|
||||
*/
|
||||
public function findFile(string $index, ?string $defaultValue = null)
|
||||
public function findFile($index, $defaultValue = null)
|
||||
{
|
||||
return $this->file[$index] ?? $defaultValue;
|
||||
return isset($this->file[$index]) ? $this->file[$index] : $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,9 +194,9 @@ class InputHandler
|
||||
* @param string|null $defaultValue
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function findGet(string $index, ?string $defaultValue = null)
|
||||
public function findGet($index, $defaultValue = null)
|
||||
{
|
||||
return $this->get[$index] ?? $defaultValue;
|
||||
return isset($this->get[$index]) ? $this->get[$index] : $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,27 +207,27 @@ class InputHandler
|
||||
* @param array|string|null $methods
|
||||
* @return IInputItem|string
|
||||
*/
|
||||
public function getObject(string $index, ?string $defaultValue = null, $methods = null)
|
||||
public function getObject($index, $defaultValue = null, $methods = null)
|
||||
{
|
||||
if ($methods !== null && \is_string($methods) === true) {
|
||||
if ($methods !== null && is_string($methods) === true) {
|
||||
$methods = [$methods];
|
||||
}
|
||||
|
||||
$element = null;
|
||||
|
||||
if ($methods === null || \in_array('get', $methods, true) === true) {
|
||||
if ($methods === null || in_array('get', $methods)) {
|
||||
$element = $this->findGet($index);
|
||||
}
|
||||
|
||||
if (($element === null && $methods === null) || ($methods !== null && \in_array('post', $methods, true) === true)) {
|
||||
if (($element === null && $methods === null) || ($methods !== null && in_array('post', $methods))) {
|
||||
$element = $this->findPost($index);
|
||||
}
|
||||
|
||||
if (($element === null && $methods === null) || ($methods !== null && \in_array('file', $methods, true) === true)) {
|
||||
if (($element === null && $methods === null) || ($methods !== null && in_array('file', $methods))) {
|
||||
$element = $this->findFile($index);
|
||||
}
|
||||
|
||||
return $element ?? $defaultValue;
|
||||
return ($element !== null) ? $element : $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +238,7 @@ class InputHandler
|
||||
* @param array|string|null $methods
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function get(string $index, ?string $defaultValue = null, $methods = null)
|
||||
public function get($index, $defaultValue = null, $methods = null)
|
||||
{
|
||||
$input = $this->getObject($index, $defaultValue, $methods);
|
||||
|
||||
@@ -264,7 +255,7 @@ class InputHandler
|
||||
* @param string $index
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $index): bool
|
||||
public function exists($index)
|
||||
{
|
||||
return ($this->getObject($index) !== null);
|
||||
}
|
||||
@@ -274,23 +265,31 @@ class InputHandler
|
||||
* @param array|null $filter Only take items in filter
|
||||
* @return array
|
||||
*/
|
||||
public function all(array $filter = null): array
|
||||
public function all(array $filter = null)
|
||||
{
|
||||
$output = $_GET + $_POST;
|
||||
$output = $_POST;
|
||||
|
||||
if ($this->request->getMethod() === 'post') {
|
||||
|
||||
$contents = file_get_contents('php://input');
|
||||
|
||||
if (strpos(trim($contents), '{') === 0) {
|
||||
$post = json_decode($contents, true);
|
||||
if ($post !== false) {
|
||||
$output += $post;
|
||||
$output = json_decode($contents, true);
|
||||
if ($output === false) {
|
||||
$output = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ($filter !== null) ? array_intersect_key($output, array_flip($filter)) : $output;
|
||||
$output = array_merge($_GET, $output);
|
||||
|
||||
if ($filter !== null) {
|
||||
$output = array_filter($output, function ($key) use ($filter) {
|
||||
return (in_array($key, $filter) === true);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
use Pecee\Exceptions\InvalidArgumentException;
|
||||
|
||||
class InputFile implements IInputItem
|
||||
{
|
||||
public $index;
|
||||
@@ -11,45 +8,43 @@ class InputFile implements IInputItem
|
||||
public $filename;
|
||||
public $size;
|
||||
public $type;
|
||||
public $errors;
|
||||
public $error;
|
||||
public $tmpName;
|
||||
|
||||
public function __construct(string $index)
|
||||
public function __construct($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
$this->errors = 0;
|
||||
|
||||
// Make the name human friendly, by replace _ with space
|
||||
$this->name = ucfirst(str_replace('_', ' ', strtolower($this->index)));
|
||||
$this->name = ucfirst(str_replace('_', ' ', $this->index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from array
|
||||
*
|
||||
* @param array $values
|
||||
* @throws InvalidArgumentException
|
||||
* @throws \InvalidArgumentException
|
||||
* @return static
|
||||
*/
|
||||
public static function createFromArray(array $values): self
|
||||
public static function createFromArray(array $values)
|
||||
{
|
||||
if (isset($values['index']) === false) {
|
||||
throw new InvalidArgumentException('Index key is required');
|
||||
if (!isset($values['index'])) {
|
||||
throw new \InvalidArgumentException('Index key is required');
|
||||
}
|
||||
|
||||
/* Easy way of ensuring that all indexes-are set and not filling the screen with isset() */
|
||||
|
||||
$values += [
|
||||
$values = array_merge([
|
||||
'tmp_name' => null,
|
||||
'type' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
'error' => null,
|
||||
];
|
||||
], $values);
|
||||
|
||||
return (new static($values['index']))
|
||||
->setSize((int)$values['size'])
|
||||
->setError($values['error'])
|
||||
->setSize($values['size'])
|
||||
->setType($values['type'])
|
||||
->setTmpName($values['tmp_name'])
|
||||
->setFilename($values['name']);
|
||||
@@ -59,7 +54,7 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex(): string
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
@@ -67,9 +62,9 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* Set input index
|
||||
* @param string $index
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setIndex(string $index): IInputItem
|
||||
public function setIndex($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
@@ -79,7 +74,7 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSize(): string
|
||||
public function getSize()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
@@ -87,9 +82,9 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* Set file size
|
||||
* @param int $size
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setSize(int $size): IInputItem
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
@@ -100,7 +95,7 @@ class InputFile implements IInputItem
|
||||
* Get mime-type of file
|
||||
* @return string
|
||||
*/
|
||||
public function getMime(): string
|
||||
public function getMime()
|
||||
{
|
||||
return $this->getType();
|
||||
}
|
||||
@@ -108,7 +103,7 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
@@ -116,9 +111,9 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* Set type
|
||||
* @param string $type
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setType(string $type): IInputItem
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
@@ -130,7 +125,7 @@ class InputFile implements IInputItem
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtension(): string
|
||||
public function getExtension()
|
||||
{
|
||||
return pathinfo($this->getFilename(), PATHINFO_EXTENSION);
|
||||
}
|
||||
@@ -140,7 +135,7 @@ class InputFile implements IInputItem
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -150,9 +145,9 @@ class InputFile implements IInputItem
|
||||
* Useful for adding validation etc.
|
||||
*
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setName(string $name): IInputItem
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -163,9 +158,9 @@ class InputFile implements IInputItem
|
||||
* Set filename
|
||||
*
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setFilename($name): IInputItem
|
||||
public function setFilename($name)
|
||||
{
|
||||
$this->filename = $name;
|
||||
|
||||
@@ -177,7 +172,7 @@ class InputFile implements IInputItem
|
||||
*
|
||||
* @return string mixed
|
||||
*/
|
||||
public function getFilename(): string
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
@@ -188,7 +183,7 @@ class InputFile implements IInputItem
|
||||
* @param string $destination
|
||||
* @return bool
|
||||
*/
|
||||
public function move($destination): bool
|
||||
public function move($destination)
|
||||
{
|
||||
return move_uploaded_file($this->tmpName, $destination);
|
||||
}
|
||||
@@ -198,17 +193,17 @@ class InputFile implements IInputItem
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContents(): string
|
||||
public function getContents()
|
||||
{
|
||||
return file_get_contents($this->tmpName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an upload error occurred.
|
||||
* Return true if an upload error occured.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasError(): bool
|
||||
public function hasError()
|
||||
{
|
||||
return ($this->getError() !== 0);
|
||||
}
|
||||
@@ -218,20 +213,20 @@ class InputFile implements IInputItem
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getError(): string
|
||||
public function getError()
|
||||
{
|
||||
return $this->errors;
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set error
|
||||
*
|
||||
* @param int $error
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setError($error): IInputItem
|
||||
public function setError($error)
|
||||
{
|
||||
$this->errors = (int)$error;
|
||||
$this->error = (int)$error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -239,7 +234,7 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTmpName(): string
|
||||
public function getTmpName()
|
||||
{
|
||||
return $this->tmpName;
|
||||
}
|
||||
@@ -247,9 +242,9 @@ class InputFile implements IInputItem
|
||||
/**
|
||||
* Set file temp. name
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setTmpName($name): IInputItem
|
||||
public function setTmpName($name)
|
||||
{
|
||||
$this->tmpName = $name;
|
||||
|
||||
@@ -261,31 +256,14 @@ class InputFile implements IInputItem
|
||||
return $this->getTmpName();
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->getFilename();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function setValue(string $value): IInputItem
|
||||
{
|
||||
$this->filename = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'tmp_name' => $this->tmpName,
|
||||
'type' => $this->type,
|
||||
'size' => $this->size,
|
||||
'name' => $this->name,
|
||||
'error' => $this->errors,
|
||||
'filename' => $this->filename,
|
||||
'name' => $this->filename,
|
||||
'error' => $this->error,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
class InputItem implements IInputItem
|
||||
@@ -8,24 +7,24 @@ class InputItem implements IInputItem
|
||||
public $name;
|
||||
public $value;
|
||||
|
||||
public function __construct(string $index, ?string $value = null)
|
||||
public function __construct($index, $value = null)
|
||||
{
|
||||
$this->index = $index;
|
||||
$this->value = $value;
|
||||
|
||||
// Make the name human friendly, by replace _ with space
|
||||
$this->name = ucfirst(str_replace('_', ' ', strtolower($this->index)));
|
||||
$this->name = ucfirst(str_replace('_', ' ', $this->index));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex(): string
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
public function setIndex(string $index): IInputItem
|
||||
public function setIndex($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
@@ -35,7 +34,7 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -43,9 +42,9 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* Set input name
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setName(string $name): IInputItem
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -55,7 +54,7 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue(): string
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
@@ -63,9 +62,9 @@ class InputItem implements IInputItem
|
||||
/**
|
||||
* Set input value
|
||||
* @param string $value
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setValue(string $value): IInputItem
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Middleware;
|
||||
|
||||
use Pecee\CsrfToken;
|
||||
use Pecee\Http\Middleware\Exceptions\TokenMismatchException;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\Http\Security\CookieTokenProvider;
|
||||
use Pecee\Http\Security\ITokenProvider;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
class BaseCsrfVerifier implements IMiddleware
|
||||
{
|
||||
public const POST_KEY = 'csrf-token';
|
||||
public const HEADER_KEY = 'X-CSRF-TOKEN';
|
||||
const POST_KEY = 'csrf-token';
|
||||
const HEADER_KEY = 'X-CSRF-TOKEN';
|
||||
|
||||
protected $except;
|
||||
protected $tokenProvider;
|
||||
protected $csrfToken;
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* BaseCsrfVerifier constructor.
|
||||
* @throws \Pecee\Http\Security\Exceptions\SecurityException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->tokenProvider = new CookieTokenProvider();
|
||||
$this->csrfToken = new CsrfToken();
|
||||
|
||||
// Generate or get the CSRF-Token from Cookie.
|
||||
$this->token = ($this->hasToken() === false) ? $this->generateToken() : $this->csrfToken->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,23 +28,23 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function skip(Request $request): bool
|
||||
protected function skip(Request $request)
|
||||
{
|
||||
if ($this->except === null || \count($this->except) === 0) {
|
||||
if ($this->except === null || is_array($this->except) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max = \count($this->except) - 1;
|
||||
$max = count($this->except) - 1;
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
$url = $this->except[$i];
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
if ($url[\strlen($url) - 1] === '*') {
|
||||
if ($url[strlen($url) - 1] === '*') {
|
||||
$url = rtrim($url, '*');
|
||||
$skip = $request->getUrl()->contains($url);
|
||||
$skip = (stripos($request->getUri(), $url) === 0);
|
||||
} else {
|
||||
$skip = ($url === $request->getUrl()->getOriginalUrl());
|
||||
$skip = ($url === rtrim($request->getUri(), '/'));
|
||||
}
|
||||
|
||||
if ($skip === true) {
|
||||
@@ -56,47 +55,46 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request
|
||||
*
|
||||
* @param Request $request
|
||||
* @throws TokenMismatchException
|
||||
*/
|
||||
public function handle(Request $request): void
|
||||
public function handle(Request $request, ILoadableRoute &$route = null)
|
||||
{
|
||||
|
||||
if ($this->skip($request) === false && \in_array($request->getMethod(), ['post', 'put', 'delete'], true) === true) {
|
||||
if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete'], false) === true) {
|
||||
|
||||
$token = $request->getInputHandler()->get(static::POST_KEY, null, 'post');
|
||||
$token = $request->getInput()->get(static::POST_KEY, null, 'post');
|
||||
|
||||
// If the token is not posted, check headers for valid x-csrf-token
|
||||
if ($token === null) {
|
||||
$token = $request->getHeader(static::HEADER_KEY);
|
||||
}
|
||||
|
||||
if ($this->tokenProvider->validate($token) === false) {
|
||||
throw new TokenMismatchException('Invalid CSRF-token.');
|
||||
if ($this->csrfToken->validate($token) === false) {
|
||||
throw new TokenMismatchException('Invalid csrf-token.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Refresh existing token
|
||||
$this->tokenProvider->refresh();
|
||||
|
||||
}
|
||||
|
||||
public function getTokenProvider(): ITokenProvider
|
||||
public function generateToken()
|
||||
{
|
||||
return $this->tokenProvider;
|
||||
$token = CsrfToken::generateToken();
|
||||
$this->csrfToken->setToken($token);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token provider
|
||||
* @param ITokenProvider $provider
|
||||
*/
|
||||
public function setTokenProvider(ITokenProvider $provider): void
|
||||
public function hasToken()
|
||||
{
|
||||
$this->tokenProvider = $provider;
|
||||
if ($this->token !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->csrfToken->hasToken();
|
||||
}
|
||||
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Middleware\Exceptions;
|
||||
|
||||
class TokenMismatchException extends \Exception
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Middleware;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
interface IMiddleware
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ILoadableRoute $route
|
||||
* @return Request|null
|
||||
*/
|
||||
public function handle(Request $request): void;
|
||||
public function handle(Request $request, ILoadableRoute &$route);
|
||||
|
||||
}
|
||||
+73
-217
@@ -1,79 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http;
|
||||
|
||||
use Pecee\Http\Input\InputHandler;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
use Pecee\SimpleRouter\Route\RouteUrl;
|
||||
use Pecee\SimpleRouter\SimpleRouter;
|
||||
use Pecee\Http\Input\Input;
|
||||
|
||||
class Request
|
||||
{
|
||||
private $data = [];
|
||||
protected $headers = [];
|
||||
protected $data = [];
|
||||
protected $headers;
|
||||
protected $host;
|
||||
protected $url;
|
||||
protected $uri;
|
||||
protected $method;
|
||||
protected $inputHandler;
|
||||
protected $input;
|
||||
|
||||
protected $hasRewrite = false;
|
||||
|
||||
/**
|
||||
* @var ILoadableRoute|null
|
||||
*/
|
||||
protected $rewriteRoute;
|
||||
protected $rewriteUrl;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $loadedRoutes = [];
|
||||
|
||||
/**
|
||||
* Request constructor.
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
$this->parseHeaders();
|
||||
$this->host = $this->getHeader('http-host');
|
||||
$this->uri = $this->getHeader('request-uri');
|
||||
$this->input = new Input($this);
|
||||
$this->method = strtolower($this->input->get('_method', $this->getHeader('request-method'), 'post'));
|
||||
}
|
||||
|
||||
protected function parseHeaders()
|
||||
{
|
||||
$this->headers = [];
|
||||
|
||||
$max = count($_SERVER) - 1;
|
||||
$keys = array_keys($_SERVER);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
$key = $keys[$i];
|
||||
$value = $_SERVER[$key];
|
||||
|
||||
$this->headers[strtolower($key)] = $value;
|
||||
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
|
||||
}
|
||||
|
||||
$this->setHost($this->getHeader('http-host'));
|
||||
|
||||
// Check if special IIS header exist, otherwise use default.
|
||||
$this->setUrl($this->getHeader('unencoded-url', $this->getHeader('request-uri')));
|
||||
|
||||
$this->inputHandler = new InputHandler($this);
|
||||
$this->method = strtolower($this->inputHandler->get('_method', $this->getHeader('request-method')));
|
||||
}
|
||||
|
||||
public function isSecure(): bool
|
||||
public function isSecure()
|
||||
{
|
||||
return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Url
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): Url
|
||||
public function getUri()
|
||||
{
|
||||
return $this->url;
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getHost(): ?string
|
||||
public function getHost()
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod(): ?string
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
@@ -82,7 +71,7 @@ class Request
|
||||
* Get http basic auth user
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUser(): ?string
|
||||
public function getUser()
|
||||
{
|
||||
return $this->getHeader('php-auth-user');
|
||||
}
|
||||
@@ -91,7 +80,7 @@ class Request
|
||||
* Get http basic auth password
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword(): ?string
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->getHeader('php-auth-pw');
|
||||
}
|
||||
@@ -100,16 +89,16 @@ class Request
|
||||
* Get all headers
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id address
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getIp(): ?string
|
||||
public function getIp()
|
||||
{
|
||||
if ($this->getHeader('http-cf-connecting-ip') !== null) {
|
||||
return $this->getHeader('http-cf-connecting-ip');
|
||||
@@ -122,31 +111,20 @@ class Request
|
||||
return $this->getHeader('remote-addr');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remote address/ip
|
||||
*
|
||||
* @alias static::getIp
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRemoteAddr(): ?string
|
||||
{
|
||||
return $this->getIp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get referer
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getReferer(): ?string
|
||||
public function getReferer()
|
||||
{
|
||||
return $this->getHeader('http-referer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user agent
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getUserAgent(): ?string
|
||||
public function getUserAgent()
|
||||
{
|
||||
return $this->getHeader('http-user-agent');
|
||||
}
|
||||
@@ -159,18 +137,35 @@ class Request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getHeader($name, $defaultValue = null): ?string
|
||||
public function getHeader($name, $defaultValue = null)
|
||||
{
|
||||
return $this->headers[strtolower($name)] ?? $defaultValue;
|
||||
if (isset($this->headers[strtolower($name)])) {
|
||||
return $this->headers[strtolower($name)];
|
||||
}
|
||||
|
||||
$max = count($_SERVER) - 1;
|
||||
$keys = array_keys($_SERVER);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$key = $keys[$i];
|
||||
$name = $_SERVER[$key];
|
||||
|
||||
if ($key === $name) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input class
|
||||
* @return InputHandler
|
||||
* @return Input
|
||||
*/
|
||||
public function getInputHandler(): InputHandler
|
||||
public function getInput()
|
||||
{
|
||||
return $this->inputHandler;
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,43 +175,32 @@ class Request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFormatAccepted($format): bool
|
||||
public function isFormatAccepted($format)
|
||||
{
|
||||
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request is made through Ajax
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAjax(): bool
|
||||
{
|
||||
return (strtolower($this->getHeader('http-x-requested-with')) === 'xmlhttprequest');
|
||||
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) > -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get accept formats
|
||||
* @return array
|
||||
*/
|
||||
public function getAcceptFormats(): array
|
||||
public function getAcceptFormats()
|
||||
{
|
||||
return explode(',', $this->getHeader('http-accept'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|Url $url
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @param string $uri
|
||||
*/
|
||||
public function setUrl($url): void
|
||||
public function setUri($uri)
|
||||
{
|
||||
$this->url = ($url instanceof Url) ? $url : new Url($url);
|
||||
$this->uri = $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $host
|
||||
* @param string $host
|
||||
*/
|
||||
public function setHost(?string $host): void
|
||||
public function setHost($host)
|
||||
{
|
||||
$this->host = $host;
|
||||
}
|
||||
@@ -224,142 +208,14 @@ class Request
|
||||
/**
|
||||
* @param string $method
|
||||
*/
|
||||
public function setMethod(string $method): void
|
||||
public function setMethod($method)
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set rewrite route
|
||||
*
|
||||
* @param ILoadableRoute $route
|
||||
* @return static
|
||||
*/
|
||||
public function setRewriteRoute(ILoadableRoute $route): self
|
||||
{
|
||||
$this->hasRewrite = true;
|
||||
$this->rewriteRoute = SimpleRouter::addDefaultNamespace($route);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rewrite route
|
||||
*
|
||||
* @return ILoadableRoute|null
|
||||
*/
|
||||
public function getRewriteRoute(): ?ILoadableRoute
|
||||
{
|
||||
return $this->rewriteRoute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rewrite url
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRewriteUrl(): ?string
|
||||
{
|
||||
return $this->rewriteUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set rewrite url
|
||||
*
|
||||
* @param string $rewriteUrl
|
||||
* @return static
|
||||
*/
|
||||
public function setRewriteUrl(string $rewriteUrl): self
|
||||
{
|
||||
$this->hasRewrite = true;
|
||||
$this->rewriteUrl = rtrim($rewriteUrl, '/') . '/';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set rewrite callback
|
||||
* @param string|\Closure $callback
|
||||
* @return static
|
||||
*/
|
||||
public function setRewriteCallback($callback): self
|
||||
{
|
||||
$this->hasRewrite = true;
|
||||
|
||||
return $this->setRewriteRoute(new RouteUrl($this->getUrl()->getPath(), $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get loaded route
|
||||
* @return ILoadableRoute|null
|
||||
*/
|
||||
public function getLoadedRoute(): ?ILoadableRoute
|
||||
{
|
||||
return (\count($this->loadedRoutes) > 0) ? end($this->loadedRoutes) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all loaded routes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLoadedRoutes(): array
|
||||
{
|
||||
return $this->loadedRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set loaded routes
|
||||
*
|
||||
* @param array $routes
|
||||
* @return static
|
||||
*/
|
||||
public function setLoadedRoutes(array $routes): self
|
||||
{
|
||||
$this->loadedRoutes = $routes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added loaded route
|
||||
*
|
||||
* @param ILoadableRoute $route
|
||||
* @return static
|
||||
*/
|
||||
public function addLoadedRoute(ILoadableRoute $route): self
|
||||
{
|
||||
$this->loadedRoutes[] = $route;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request contains a rewrite
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRewrite(): bool
|
||||
{
|
||||
return $this->hasRewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the current request contains a rewrite.
|
||||
*
|
||||
* @param bool $boolean
|
||||
* @return Request
|
||||
*/
|
||||
public function setHasRewrite(bool $boolean): self
|
||||
{
|
||||
$this->hasRewrite = $boolean;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
return array_key_exists($name, $this->data) === true;
|
||||
return array_key_exists($name, $this->data);
|
||||
}
|
||||
|
||||
public function __set($name, $value = null)
|
||||
@@ -369,7 +225,7 @@ class Request
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->data[$name] ?? null;
|
||||
return isset($this->data[$name]) ? $this->data[$name] : null;
|
||||
}
|
||||
|
||||
}
|
||||
+21
-23
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace Pecee\Http;
|
||||
|
||||
use Pecee\Exceptions\InvalidArgumentException;
|
||||
|
||||
class Response
|
||||
{
|
||||
protected $request;
|
||||
@@ -19,7 +17,7 @@ class Response
|
||||
* @param int $code
|
||||
* @return static
|
||||
*/
|
||||
public function httpCode(int $code): self
|
||||
public function httpCode($code)
|
||||
{
|
||||
http_response_code($code);
|
||||
|
||||
@@ -32,19 +30,19 @@ class Response
|
||||
* @param string $url
|
||||
* @param int $httpCode
|
||||
*/
|
||||
public function redirect(string $url, ?int $httpCode = null): void
|
||||
public function redirect($url, $httpCode = null)
|
||||
{
|
||||
if ($httpCode !== null) {
|
||||
$this->httpCode($httpCode);
|
||||
}
|
||||
|
||||
$this->header('location: ' . $url);
|
||||
exit(0);
|
||||
die();
|
||||
}
|
||||
|
||||
public function refresh(): void
|
||||
public function refresh()
|
||||
{
|
||||
$this->redirect($this->request->getUrl()->getOriginalUrl());
|
||||
$this->redirect($this->request->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +50,7 @@ class Response
|
||||
* @param string $name
|
||||
* @return static
|
||||
*/
|
||||
public function auth(string $name = ''): self
|
||||
public function auth($name = '')
|
||||
{
|
||||
$this->headers([
|
||||
'WWW-Authenticate: Basic realm="' . $name . '"',
|
||||
@@ -62,22 +60,23 @@ class Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cache(string $eTag, int $lastModifiedTime = 2592000): self
|
||||
public function cache($eTag, $lastModified = 2592000)
|
||||
{
|
||||
|
||||
$this->headers([
|
||||
'Cache-Control: public',
|
||||
sprintf('Last-Modified: %s GMT', gmdate('D, d M Y H:i:s', $lastModifiedTime)),
|
||||
sprintf('Etag: %s', $eTag),
|
||||
'Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT',
|
||||
'Etag: ' . $eTag,
|
||||
]);
|
||||
|
||||
$httpModified = $this->request->getHeader('http-if-modified-since');
|
||||
$httpIfNoneMatch = $this->request->getHeader('http-if-none-match');
|
||||
|
||||
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModifiedTime)) {
|
||||
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModified)) {
|
||||
|
||||
$this->header('HTTP/1.1 304 Not Modified');
|
||||
exit(0);
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -86,18 +85,17 @@ class Response
|
||||
/**
|
||||
* Json encode
|
||||
* @param array|\JsonSerializable $value
|
||||
* @param int $options JSON options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR.
|
||||
* @param int $dept JSON debt.
|
||||
* @throws InvalidArgumentException
|
||||
* @throws \InvalidArgumentException;
|
||||
*/
|
||||
public function json($value, ?int $options = null, int $dept = 512): void
|
||||
public function json($value)
|
||||
{
|
||||
if (($value instanceof \JsonSerializable) === false && \is_array($value) === false) {
|
||||
throw new InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
|
||||
|
||||
if (($value instanceof \JsonSerializable) === false && is_array($value) === false) {
|
||||
throw new \InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
|
||||
}
|
||||
|
||||
$this->header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode($value, $options, $dept);
|
||||
$this->header('Content-type: application/json');
|
||||
echo json_encode($value);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -106,7 +104,7 @@ class Response
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function header(string $value): self
|
||||
public function header($value)
|
||||
{
|
||||
header($value);
|
||||
|
||||
@@ -118,7 +116,7 @@ class Response
|
||||
* @param array $headers
|
||||
* @return static
|
||||
*/
|
||||
public function headers(array $headers): self
|
||||
public function headers(array $headers)
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
$this->header($header);
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Security;
|
||||
|
||||
use Pecee\Http\Security\Exceptions\SecurityException;
|
||||
|
||||
class CookieTokenProvider implements ITokenProvider
|
||||
{
|
||||
public const CSRF_KEY = 'CSRF-TOKEN';
|
||||
|
||||
protected $token;
|
||||
protected $cookieTimeoutMinutes = 120;
|
||||
|
||||
/**
|
||||
* CookieTokenProvider constructor.
|
||||
* @throws SecurityException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->token = $this->getToken();
|
||||
|
||||
if ($this->token === null) {
|
||||
$this->token = $this->generateToken();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random identifier for CSRF token
|
||||
*
|
||||
* @return string
|
||||
* @throws SecurityException
|
||||
*/
|
||||
public function generateToken(): string
|
||||
{
|
||||
try {
|
||||
return bin2hex(random_bytes(32));
|
||||
} catch (\Exception $e) {
|
||||
throw new SecurityException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate valid CSRF token
|
||||
*
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(string $token): bool
|
||||
{
|
||||
if ($this->getToken() !== null) {
|
||||
return hash_equals($token, $this->getToken());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set csrf token cookie
|
||||
* Overwrite this method to save the token to another storage like session etc.
|
||||
*
|
||||
* @param string $token
|
||||
*/
|
||||
public function setToken(string $token): void
|
||||
{
|
||||
$this->token = $token;
|
||||
setcookie(static::CSRF_KEY, $token, time() + 60 * $this->cookieTimeoutMinutes, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get csrf token
|
||||
* @param string|null $defaultValue
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken(?string $defaultValue = null): ?string
|
||||
{
|
||||
$this->token = ($this->hasToken() === true) ? $_COOKIE[static::CSRF_KEY] : null;
|
||||
|
||||
return $this->token ?? $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh existing token
|
||||
*/
|
||||
public function refresh(): void
|
||||
{
|
||||
if ($this->token !== null) {
|
||||
$this->setToken($this->token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the csrf token has been defined
|
||||
* @return bool
|
||||
*/
|
||||
public function hasToken(): bool
|
||||
{
|
||||
return isset($_COOKIE[static::CSRF_KEY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timeout for cookie in minutes
|
||||
* @return int
|
||||
*/
|
||||
public function getCookieTimeoutMinutes(): int
|
||||
{
|
||||
return $this->cookieTimeoutMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie timeout in minutes
|
||||
* @param int $minutes
|
||||
*/
|
||||
public function setCookieTimeoutMinutes(int $minutes): void
|
||||
{
|
||||
$this->cookieTimeoutMinutes = $minutes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Security\Exceptions;
|
||||
|
||||
class SecurityException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http\Security;
|
||||
|
||||
interface ITokenProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* Refresh existing token
|
||||
*/
|
||||
public function refresh(): void;
|
||||
|
||||
/**
|
||||
* Validate valid CSRF token
|
||||
*
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(string $token): bool;
|
||||
|
||||
/**
|
||||
* Get token token
|
||||
*
|
||||
* @param string|null $defaultValue
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken(?string $defaultValue = null): ?string;
|
||||
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\Http;
|
||||
|
||||
use Pecee\Http\Exceptions\MalformedUrlException;
|
||||
|
||||
class Url
|
||||
{
|
||||
private $originalUrl;
|
||||
private $data = [
|
||||
'scheme' => null,
|
||||
'host' => null,
|
||||
'port' => null,
|
||||
'user' => null,
|
||||
'pass' => null,
|
||||
'path' => null,
|
||||
'query' => null,
|
||||
'fragment' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* Url constructor.
|
||||
* @param string $url
|
||||
* @throws MalformedUrlException
|
||||
*/
|
||||
public function __construct(?string $url)
|
||||
{
|
||||
$this->originalUrl = $url;
|
||||
if ($url !== null) {
|
||||
$this->data = $this->parseUrl($url) + $this->data;
|
||||
|
||||
if (isset($this->data['path']) === true && $this->data['path'] !== '/') {
|
||||
$this->data['path'] = rtrim($this->data['path'], '/') . '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if url is using a secure protocol like https
|
||||
* @return bool
|
||||
*/
|
||||
public function isSecure(): bool
|
||||
{
|
||||
return (strtolower($this->getScheme()) === 'https');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if url is relative
|
||||
* @return bool
|
||||
*/
|
||||
public function isRelative(): bool
|
||||
{
|
||||
return ($this->getHost() === null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url scheme
|
||||
* @return string|null
|
||||
*/
|
||||
public function getScheme(): ?string
|
||||
{
|
||||
return $this->data['scheme'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url host
|
||||
* @return string|null
|
||||
*/
|
||||
public function getHost(): ?string
|
||||
{
|
||||
return $this->data['host'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url port
|
||||
* @return int|null
|
||||
*/
|
||||
public function getPort(): ?int
|
||||
{
|
||||
return ($this->data['port'] !== null) ? (int)$this->data['port'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse username from url
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUserName(): ?string
|
||||
{
|
||||
return $this->data['user'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse password from url
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
return $this->data['pass'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path from url
|
||||
* @return string
|
||||
*/
|
||||
public function getPath(): ?string
|
||||
{
|
||||
return $this->data['path'] ?? '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get querystring from url
|
||||
* @return string|null
|
||||
*/
|
||||
public function getQueryString(): ?string
|
||||
{
|
||||
return $this->data['query'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fragment from url (everything after #)
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFragment(): ?string
|
||||
{
|
||||
return $this->data['fragment'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOriginalUrl(): string
|
||||
{
|
||||
return $this->originalUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* UTF-8 aware parse_url() replacement.
|
||||
* @param string $url
|
||||
* @param int $component
|
||||
* @throws MalformedUrlException
|
||||
* @return array
|
||||
*/
|
||||
public function parseUrl(string $url, int $component = -1): array
|
||||
{
|
||||
$encodedUrl = preg_replace_callback(
|
||||
'/[^:\/@?&=#]+/u',
|
||||
function ($matches) {
|
||||
return urlencode($matches[0]);
|
||||
},
|
||||
$url
|
||||
);
|
||||
|
||||
$parts = parse_url($encodedUrl, $component);
|
||||
|
||||
if ($parts === false) {
|
||||
throw new MalformedUrlException('Malformed URL: ' . $url);
|
||||
}
|
||||
|
||||
return array_map('urldecode', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get position of value.
|
||||
* Returns -1 on failure.
|
||||
*
|
||||
* @param string $value
|
||||
* @return int
|
||||
*/
|
||||
public function indexOf(string $value): int
|
||||
{
|
||||
$index = stripos($this->getOriginalUrl(), $value);
|
||||
|
||||
return ($index === false) ? -1 : $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if url contains value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(string $value): bool
|
||||
{
|
||||
return (stripos($this->getOriginalUrl(), $value) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data array with information about the url
|
||||
* @return array
|
||||
*/
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getOriginalUrl();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Exceptions;
|
||||
|
||||
class HttpException extends \Exception
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Exceptions;
|
||||
|
||||
class NotFoundHttpException extends HttpException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
@@ -10,6 +9,7 @@ interface IRouterBootManager
|
||||
* Called when router loads it's routes
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Request
|
||||
*/
|
||||
public function boot(Request $request): void;
|
||||
public function boot(Request $request);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
interface IControllerRoute extends IRoute
|
||||
@@ -9,7 +8,7 @@ interface IControllerRoute extends IRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getController(): string;
|
||||
public function getController();
|
||||
|
||||
/**
|
||||
* Set controller class-name
|
||||
@@ -17,6 +16,21 @@ interface IControllerRoute extends IRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController(string $controller): self;
|
||||
public function setController($controller);
|
||||
|
||||
/**
|
||||
* Return active method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* Set active method
|
||||
*
|
||||
* @param string $method
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod($method);
|
||||
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Handlers\IExceptionHandler;
|
||||
use Pecee\Http\Request;
|
||||
|
||||
interface IGroupRoute extends IRoute
|
||||
@@ -13,21 +11,13 @@ interface IGroupRoute extends IRoute
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function matchDomain(Request $request): bool;
|
||||
|
||||
/**
|
||||
* Add exception handler
|
||||
*
|
||||
* @param IExceptionHandler|string $handler
|
||||
* @return static
|
||||
*/
|
||||
public function addExceptionHandler($handler): self;
|
||||
public function matchDomain(Request $request);
|
||||
|
||||
/**
|
||||
* Set exception-handlers for group
|
||||
*
|
||||
* @param array $handlers
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setExceptionHandlers(array $handlers);
|
||||
|
||||
@@ -36,35 +26,35 @@ interface IGroupRoute extends IRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExceptionHandlers(): array;
|
||||
public function getExceptionHandlers();
|
||||
|
||||
/**
|
||||
* Get domains for domain.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDomains(): array;
|
||||
public function getDomains();
|
||||
|
||||
/**
|
||||
* Set allowed domains for group.
|
||||
*
|
||||
* @param array $domains
|
||||
* @return static
|
||||
* @return $this
|
||||
*/
|
||||
public function setDomains(array $domains): self;
|
||||
public function setDomains(array $domains);
|
||||
|
||||
/**
|
||||
* Set prefix that child-routes will inherit.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return static
|
||||
* @return string
|
||||
*/
|
||||
public function setPrefix($prefix): self;
|
||||
public function setPrefix($prefix);
|
||||
|
||||
/**
|
||||
* Get prefix.
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix(): ?string;
|
||||
public function getPrefix();
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
interface ILoadableRoute extends IRoute
|
||||
{
|
||||
@@ -16,35 +14,26 @@ interface ILoadableRoute extends IRoute
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
*/
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string;
|
||||
public function findUrl($method = null, $parameters = null, $name = null);
|
||||
|
||||
/**
|
||||
* Loads and renders middleware-classes
|
||||
* Loads and renders middlewares-classes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @param ILoadableRoute $route
|
||||
*/
|
||||
public function loadMiddleware(Request $request, Router $router): void;
|
||||
public function loadMiddleware(Request $request, ILoadableRoute $route);
|
||||
|
||||
/**
|
||||
* Get url
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): string;
|
||||
public function getUrl();
|
||||
|
||||
/**
|
||||
* Set url
|
||||
* @param string $url
|
||||
* @return static
|
||||
*/
|
||||
public function setUrl(string $url): self;
|
||||
public function setUrl($url);
|
||||
|
||||
/**
|
||||
* Returns the provided name for the router.
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): ?string;
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Check if route has given name.
|
||||
@@ -52,22 +41,22 @@ interface ILoadableRoute extends IRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName(string $name): bool;
|
||||
public function hasName($name);
|
||||
|
||||
/**
|
||||
* Sets the router name, which makes it easier to obtain the url or router at a later point.
|
||||
*
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setName(string $name): self;
|
||||
public function setName($name);
|
||||
|
||||
/**
|
||||
* Get regular expression match used for matching route (if defined).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMatch(): ?string;
|
||||
public function getMatch();
|
||||
|
||||
/**
|
||||
* Add regular expression match for the entire route.
|
||||
@@ -75,6 +64,6 @@ interface ILoadableRoute extends IRoute
|
||||
* @param string $regex
|
||||
* @return static
|
||||
*/
|
||||
public function setMatch($regex): self;
|
||||
public function setMatch($regex);
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
interface IPartialGroupRoute
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,31 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
interface IRoute
|
||||
{
|
||||
/**
|
||||
* Method called to check if a domain matches
|
||||
*
|
||||
* @param string $route
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function matchRoute($route, Request $request): bool;
|
||||
public function matchRoute(Request $request);
|
||||
|
||||
/**
|
||||
* Called when route is matched.
|
||||
* Returns class to be rendered.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
|
||||
* @return string
|
||||
* @return void
|
||||
*/
|
||||
public function renderRoute(Request $request, Router $router): ?string;
|
||||
public function renderRoute(Request $request);
|
||||
|
||||
/**
|
||||
* Returns callback name/identifier for the current route based on the callback.
|
||||
@@ -34,50 +30,50 @@ interface IRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier(): string;
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Set allowed request methods
|
||||
*
|
||||
* @param array $methods
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setRequestMethods(array $methods): self;
|
||||
public function setRequestMethods(array $methods);
|
||||
|
||||
/**
|
||||
* Get allowed request methods
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRequestMethods(): array;
|
||||
public function getRequestMethods();
|
||||
|
||||
/**
|
||||
* @return IRoute|null
|
||||
*/
|
||||
public function getParent(): ?IRoute;
|
||||
public function getParent();
|
||||
|
||||
/**
|
||||
* Get the group for the route.
|
||||
*
|
||||
* @return IGroupRoute|null
|
||||
*/
|
||||
public function getGroup(): ?IGroupRoute;
|
||||
public function getGroup();
|
||||
|
||||
/**
|
||||
* Set group
|
||||
*
|
||||
* @param IGroupRoute $group
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setGroup(IGroupRoute $group): self;
|
||||
public function setGroup(IGroupRoute $group);
|
||||
|
||||
/**
|
||||
* Set parent route
|
||||
*
|
||||
* @param IRoute $parent
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setParent(IRoute $parent): self;
|
||||
public function setParent(IRoute $parent);
|
||||
|
||||
/**
|
||||
* Set callback
|
||||
@@ -85,64 +81,44 @@ interface IRoute
|
||||
* @param string $callback
|
||||
* @return static
|
||||
*/
|
||||
public function setCallback($callback): self;
|
||||
public function setCallback($callback);
|
||||
|
||||
/**
|
||||
* @return string|callable
|
||||
* @return string
|
||||
*/
|
||||
public function getCallback();
|
||||
|
||||
/**
|
||||
* Return active method
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMethod(): ?string;
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* Set active method
|
||||
*
|
||||
* @param string $method
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod(string $method): self;
|
||||
public function getClass();
|
||||
|
||||
/**
|
||||
* Get class
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getClass(): ?string;
|
||||
public function setMethod($method);
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setNamespace(string $namespace): self;
|
||||
public function setNamespace($namespace);
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace(): ?string;
|
||||
public function getNamespace();
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setDefaultNamespace($namespace): IRoute;
|
||||
public function setDefaultNamespace($namespace);
|
||||
|
||||
/**
|
||||
* Get default namespace
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDefaultNamespace(): ?string;
|
||||
public function getDefaultNamespace();
|
||||
|
||||
/**
|
||||
* Get parameter names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWhere(): array;
|
||||
public function getWhere();
|
||||
|
||||
/**
|
||||
* Set parameter names.
|
||||
@@ -150,45 +126,45 @@ interface IRoute
|
||||
* @param array $options
|
||||
* @return static
|
||||
*/
|
||||
public function setWhere(array $options): self;
|
||||
public function setWhere(array $options);
|
||||
|
||||
/**
|
||||
* Get parameters
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters(): array;
|
||||
public function getParameters();
|
||||
|
||||
/**
|
||||
* Get parameters
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setParameters(array $parameters): self;
|
||||
public function setParameters(array $parameters);
|
||||
|
||||
/**
|
||||
* Merge with information from another route.
|
||||
*
|
||||
* @param array $settings
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setSettings(array $settings, bool $merge = false): self;
|
||||
public function setSettings(array $settings, $merge = false);
|
||||
|
||||
/**
|
||||
* Export route settings to array so they can be merged with another route.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array;
|
||||
public function toArray();
|
||||
|
||||
/**
|
||||
* Get middlewares array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMiddlewares(): array;
|
||||
public function getMiddlewares();
|
||||
|
||||
/**
|
||||
* Set middleware class-name
|
||||
@@ -196,14 +172,14 @@ interface IRoute
|
||||
* @param string $middleware
|
||||
* @return static
|
||||
*/
|
||||
public function addMiddleware($middleware): self;
|
||||
public function setMiddleware($middleware);
|
||||
|
||||
/**
|
||||
* Set middlewares array
|
||||
*
|
||||
* @param array $middlewares
|
||||
* @return static
|
||||
* @return $this
|
||||
*/
|
||||
public function setMiddlewares(array $middlewares): self;
|
||||
public function setMiddlewares(array $middlewares);
|
||||
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Exceptions\HttpException;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
{
|
||||
@@ -25,40 +23,50 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* Loads and renders middlewares-classes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @param ILoadableRoute $route
|
||||
* @throws HttpException
|
||||
*/
|
||||
public function loadMiddleware(Request $request, Router $router): void
|
||||
public function loadMiddleware(Request $request, ILoadableRoute $route)
|
||||
{
|
||||
$router->debug('Loading middlewares');
|
||||
if (count($this->getMiddlewares()) > 0) {
|
||||
|
||||
foreach ($this->getMiddlewares() as $middleware) {
|
||||
$max = count($this->getMiddlewares());
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
|
||||
$middleware = $this->getMiddlewares()[$i];
|
||||
|
||||
if (\is_object($middleware) === false) {
|
||||
$middleware = $this->loadClass($middleware);
|
||||
}
|
||||
|
||||
if (($middleware instanceof IMiddleware) === false) {
|
||||
throw new HttpException($middleware . ' must be inherit the IMiddleware interface');
|
||||
}
|
||||
if (!($middleware instanceof IMiddleware)) {
|
||||
throw new HttpException($middleware . ' must be instance of Middleware');
|
||||
}
|
||||
|
||||
$router->debug('Loading middleware "%s"', \get_class($middleware));
|
||||
$middleware->handle($request);
|
||||
$router->debug('Finished loading middleware');
|
||||
$middleware->handle($request, $route);
|
||||
}
|
||||
}
|
||||
|
||||
$router->debug('Finished loading middlewares');
|
||||
}
|
||||
|
||||
public function matchRegex(Request $request, $url): ?bool
|
||||
public function matchRegex(Request $request, $url)
|
||||
{
|
||||
|
||||
/* Match on custom defined regular expression */
|
||||
|
||||
if ($this->regex === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((bool)preg_match($this->regex, $request->getHost() . $url) !== false);
|
||||
$parameters = [];
|
||||
|
||||
if (preg_match($this->regex, $request->getHost() . $url, $parameters) > 0) {
|
||||
|
||||
/* Remove global match */
|
||||
$this->parameters = array_slice($parameters, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,15 +75,15 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $url
|
||||
* @return static
|
||||
*/
|
||||
public function setUrl(string $url): ILoadableRoute
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
|
||||
|
||||
if (strpos($this->url, $this->paramModifiers[0]) !== false) {
|
||||
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
|
||||
if ((bool)preg_match_all('/' . $regex . '/u', $this->url, $matches) !== false) {
|
||||
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
|
||||
$this->parameters = array_fill_keys($matches[1], null);
|
||||
}
|
||||
}
|
||||
@@ -83,7 +91,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
@@ -93,18 +101,16 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* Used when calling the url() helper.
|
||||
*
|
||||
* @param string|null $method
|
||||
* @param string|array|null $parameters
|
||||
* @param array|null $parameters
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
*/
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string
|
||||
public function findUrl($method = null, $parameters = null, $name = null)
|
||||
{
|
||||
$url = $this->getUrl();
|
||||
|
||||
$group = $this->getGroup();
|
||||
|
||||
if ($group !== null && \count($group->getDomains()) !== 0) {
|
||||
$url = '//' . $group->getDomains()[0] . $url;
|
||||
if ($this->getGroup() !== null && count($this->getGroup()->getDomains()) > 0) {
|
||||
$url = '//' . $this->getGroup()->getDomains()[0] . $url;
|
||||
}
|
||||
|
||||
/* Contains parameters that aren't recognized and will be appended at the end of the url */
|
||||
@@ -119,19 +125,16 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
/* Replace any {parameter} in the url with the correct value */
|
||||
|
||||
$params = $this->getParameters();
|
||||
$max = count($params) - 1;
|
||||
$keys = array_keys($params);
|
||||
|
||||
foreach (array_keys($params) as $param) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
$param = $keys[$i];
|
||||
$value = $value = ($parameters !== null && array_key_exists($param, $parameters)) ? $parameters[$param] : $params[$param];
|
||||
|
||||
if ($parameters === '' || (\is_array($parameters) === true && \count($parameters) === 0)) {
|
||||
$value = '';
|
||||
} else {
|
||||
$p = (array)$parameters;
|
||||
$value = array_key_exists($param, $p) ? $p[$param] : $params[$param];
|
||||
|
||||
/* If parameter is specifically set to null - use the original-defined value */
|
||||
if ($value === null && isset($this->originalParameters[$param])) {
|
||||
$value = $this->originalParameters[$param];
|
||||
}
|
||||
/* If parameter is specifically set to null - use the original-defined value */
|
||||
if ($value === null && isset($this->originalParameters[$param])) {
|
||||
$value = $this->originalParameters[$param];
|
||||
}
|
||||
|
||||
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
|
||||
@@ -142,7 +145,9 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
}
|
||||
}
|
||||
|
||||
$url = '/' . ltrim($url, '/') . implode('/', $unknownParams);
|
||||
$url .= join('/', $unknownParams);
|
||||
|
||||
|
||||
|
||||
return rtrim($url, '/') . '/';
|
||||
}
|
||||
@@ -152,7 +157,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
@@ -163,9 +168,9 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName(string $name): bool
|
||||
public function hasName($name)
|
||||
{
|
||||
return strtolower($this->name) === strtolower($name);
|
||||
return (strtolower($this->name) === strtolower($name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +179,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string $regex
|
||||
* @return static
|
||||
*/
|
||||
public function setMatch($regex): ILoadableRoute
|
||||
public function setMatch($regex)
|
||||
{
|
||||
$this->regex = $regex;
|
||||
|
||||
@@ -186,7 +191,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMatch(): string
|
||||
public function getMatch()
|
||||
{
|
||||
return $this->regex;
|
||||
}
|
||||
@@ -199,7 +204,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param string|array $name
|
||||
* @return static
|
||||
*/
|
||||
public function name($name): ILoadableRoute
|
||||
public function name($name)
|
||||
{
|
||||
return $this->setName($name);
|
||||
}
|
||||
@@ -208,9 +213,9 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* Sets the router name, which makes it easier to obtain the url or router at a later point.
|
||||
*
|
||||
* @param string $name
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setName(string $name): ILoadableRoute
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -224,20 +229,17 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
public function setSettings(array $values, $merge = false)
|
||||
{
|
||||
if (isset($values['as']) === true) {
|
||||
|
||||
$name = $values['as'];
|
||||
|
||||
if (isset($values['as'])) {
|
||||
if ($this->name !== null && $merge !== false) {
|
||||
$name .= '.' . $this->name;
|
||||
$this->setName($values['as'] . '.' . $this->name);
|
||||
} else {
|
||||
$this->setName($values['as']);
|
||||
}
|
||||
|
||||
$this->setName($name);
|
||||
}
|
||||
|
||||
if (isset($values['prefix']) === true) {
|
||||
if (isset($values['prefix'])) {
|
||||
$this->setUrl($values['prefix'] . $this->getUrl());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Router;
|
||||
|
||||
abstract class Route implements IRoute
|
||||
{
|
||||
protected const PARAMETERS_REGEX_FORMAT = '%s([\w]+)(\%s?)%s';
|
||||
protected const PARAMETERS_DEFAULT_REGEX = '[\w]+';
|
||||
const PARAMETERS_REGEX_MATCH = '%s([\w]+)(\%s?)%s';
|
||||
|
||||
public const REQUEST_TYPE_GET = 'get';
|
||||
public const REQUEST_TYPE_POST = 'post';
|
||||
public const REQUEST_TYPE_PUT = 'put';
|
||||
public const REQUEST_TYPE_PATCH = 'patch';
|
||||
public const REQUEST_TYPE_OPTIONS = 'options';
|
||||
public const REQUEST_TYPE_DELETE = 'delete';
|
||||
const REQUEST_TYPE_GET = 'get';
|
||||
const REQUEST_TYPE_POST = 'post';
|
||||
const REQUEST_TYPE_PUT = 'put';
|
||||
const REQUEST_TYPE_PATCH = 'patch';
|
||||
const REQUEST_TYPE_OPTIONS = 'options';
|
||||
const REQUEST_TYPE_DELETE = 'delete';
|
||||
|
||||
public static $requestTypes = [
|
||||
self::REQUEST_TYPE_GET,
|
||||
@@ -34,16 +30,9 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $filterEmptyParams = true;
|
||||
|
||||
/**
|
||||
* Default regular expression used for parsing parameters.
|
||||
* @var string|null
|
||||
*/
|
||||
protected $defaultParameterRegex;
|
||||
protected $filterEmptyParams = false;
|
||||
protected $paramModifiers = '{}';
|
||||
protected $paramOptionalSymbol = '?';
|
||||
protected $urlRegex = '/^%s\/?$/u';
|
||||
protected $group;
|
||||
protected $parent;
|
||||
protected $callback;
|
||||
@@ -57,140 +46,91 @@ abstract class Route implements IRoute
|
||||
protected $originalParameters = [];
|
||||
protected $middlewares = [];
|
||||
|
||||
/**
|
||||
* Load class by name
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
protected function loadClass($name)
|
||||
{
|
||||
if (class_exists($name) === false) {
|
||||
throw new NotFoundHttpException(sprintf('Class "%s" does not exist', $name), 404);
|
||||
throw new NotFoundHttpException(sprintf('Class %s does not exist', $name), 404);
|
||||
}
|
||||
|
||||
return new $name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render route
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Router $router
|
||||
* @return string|null
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
public function renderRoute(Request $request, Router $router): ?string
|
||||
public function renderRoute(Request $request)
|
||||
{
|
||||
$router->debug('Starting rendering route');
|
||||
|
||||
$callback = $this->getCallback();
|
||||
|
||||
if ($callback === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$router->debug('Parsing parameters');
|
||||
$parameters = $this->getParameters();
|
||||
$router->debug('Finished parsing parameters');
|
||||
|
||||
/* Filter parameters with null-value */
|
||||
if ($this->filterEmptyParams === true) {
|
||||
$parameters = array_filter($parameters, function ($var) {
|
||||
return ($var !== null);
|
||||
});
|
||||
}
|
||||
|
||||
/* Render callback function */
|
||||
if (\is_callable($callback) === true) {
|
||||
$router->debug('Executing callback');
|
||||
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
|
||||
|
||||
/* When the callback is a function */
|
||||
call_user_func_array($this->getCallback(), $this->getParameters());
|
||||
|
||||
return \call_user_func_array($callback, $parameters);
|
||||
}
|
||||
|
||||
/* When the callback is a class + method */
|
||||
$controller = explode('@', $callback);
|
||||
|
||||
$namespace = $this->getNamespace();
|
||||
|
||||
$className = ($namespace !== null && $controller[0][0] !== '\\') ? $namespace . '\\' . $controller[0] : $controller[0];
|
||||
|
||||
$router->debug('Loading class %s', $className);
|
||||
$class = $this->loadClass($className);
|
||||
$method = $controller[1];
|
||||
|
||||
if (method_exists($class, $method) === false) {
|
||||
throw new NotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404);
|
||||
}
|
||||
|
||||
$router->debug('Executing callback');
|
||||
|
||||
return \call_user_func_array([$class, $method], $parameters);
|
||||
}
|
||||
|
||||
protected function parseParameters($route, $url, $parameterRegex = null)
|
||||
{
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
|
||||
$parameters = [];
|
||||
|
||||
// Ensures that hostnames/domains will work with parameters
|
||||
$url = '/' . ltrim($url, '/');
|
||||
|
||||
if ((bool)preg_match_all('/' . $regex . '/u', $route, $parameters) === false) {
|
||||
$urlRegex = preg_quote($route, '/');
|
||||
} else {
|
||||
|
||||
$urlParts = preg_split('/((\-?\/?)\{[^}]+\})/', $route);
|
||||
/* When the callback is a method */
|
||||
$controller = explode('@', $this->getCallback());
|
||||
$className = $this->getNamespace() . '\\' . $controller[0];
|
||||
|
||||
$class = $this->loadClass($className);
|
||||
$method = $controller[1];
|
||||
|
||||
if (method_exists($class, $method) === false) {
|
||||
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
|
||||
}
|
||||
|
||||
$parameters = $this->getParameters();
|
||||
|
||||
/* Filter parameters with null-value */
|
||||
|
||||
if ($this->filterEmptyParams === true) {
|
||||
$parameters = array_filter($parameters, function ($var) {
|
||||
return ($var !== null);
|
||||
});
|
||||
}
|
||||
|
||||
call_user_func_array([$class, $method], $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseParameters($route, $url, $parameterRegex = '[\w]+')
|
||||
{
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
|
||||
if (preg_match_all('/' . $regex . '/is', $route, $parameters)) {
|
||||
|
||||
$urlParts = preg_split('/((\-?\/?)\{[^}]+\})/is', rtrim($route, '/'));
|
||||
|
||||
foreach ($urlParts as $key => $t) {
|
||||
|
||||
$regex = '';
|
||||
|
||||
if ($key < \count($parameters[1])) {
|
||||
if ($key < (count($parameters[1]))) {
|
||||
|
||||
$name = $parameters[1][$key];
|
||||
$regex = isset($this->where[$name]) ? $this->where[$name] : $parameterRegex;
|
||||
$regex = sprintf('\-?\/?(?P<%s>%s)', $name, $regex) . $parameters[2][$key];
|
||||
|
||||
/* If custom regex is defined, use that */
|
||||
if (isset($this->where[$name]) === true) {
|
||||
$regex = $this->where[$name];
|
||||
} else {
|
||||
|
||||
/* If method specific regex is defined use that, otherwise use the default parameter regex */
|
||||
if ($parameterRegex !== null) {
|
||||
$regex = $parameterRegex;
|
||||
} else {
|
||||
$regex = $this->defaultParameterRegex ?? static::PARAMETERS_DEFAULT_REGEX;
|
||||
}
|
||||
}
|
||||
|
||||
$regex = sprintf('(?:\/|\-)%1$s(?P<%2$s>%3$s)%1$s', $parameters[2][$key], $name, $regex);
|
||||
}
|
||||
|
||||
$urlParts[$key] = preg_quote($t, '/') . $regex;
|
||||
}
|
||||
|
||||
$urlRegex = implode('', $urlParts);
|
||||
$urlRegex = join('', $urlParts);
|
||||
|
||||
} else {
|
||||
$urlRegex = preg_quote($route, '/');
|
||||
}
|
||||
|
||||
if ((bool)preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) === false) {
|
||||
return null;
|
||||
}
|
||||
if (preg_match('/^' . $urlRegex . '(\/?)$/is', $url, $matches) > 0) {
|
||||
|
||||
$values = [];
|
||||
|
||||
if (isset($parameters[1]) === true) {
|
||||
$values = [];
|
||||
|
||||
/* Only take matched parameters with name */
|
||||
foreach ((array)$parameters[1] as $name) {
|
||||
foreach ($parameters[1] as $name) {
|
||||
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $values;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,9 +140,9 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier(): string
|
||||
public function getIdentifier()
|
||||
{
|
||||
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
|
||||
if (strpos($this->callback, '@') !== false) {
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
@@ -213,9 +153,9 @@ abstract class Route implements IRoute
|
||||
* Set allowed request methods
|
||||
*
|
||||
* @param array $methods
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setRequestMethods(array $methods): IRoute
|
||||
public function setRequestMethods(array $methods)
|
||||
{
|
||||
$this->requestMethods = $methods;
|
||||
|
||||
@@ -227,7 +167,7 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRequestMethods(): array
|
||||
public function getRequestMethods()
|
||||
{
|
||||
return $this->requestMethods;
|
||||
}
|
||||
@@ -235,7 +175,7 @@ abstract class Route implements IRoute
|
||||
/**
|
||||
* @return IRoute|null
|
||||
*/
|
||||
public function getParent(): ?IRoute
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
@@ -245,7 +185,7 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return IGroupRoute|null
|
||||
*/
|
||||
public function getGroup(): ?IGroupRoute
|
||||
public function getGroup()
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
@@ -254,15 +194,12 @@ abstract class Route implements IRoute
|
||||
* Set group
|
||||
*
|
||||
* @param IGroupRoute $group
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setGroup(IGroupRoute $group): IRoute
|
||||
public function setGroup(IGroupRoute $group)
|
||||
{
|
||||
$this->group = $group;
|
||||
|
||||
/* Add/merge parent settings with child */
|
||||
$this->setSettings($group->toArray(), true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -270,9 +207,9 @@ abstract class Route implements IRoute
|
||||
* Set parent route
|
||||
*
|
||||
* @param IRoute $parent
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setParent(IRoute $parent): IRoute
|
||||
public function setParent(IRoute $parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
@@ -285,7 +222,7 @@ abstract class Route implements IRoute
|
||||
* @param string $callback
|
||||
* @return static
|
||||
*/
|
||||
public function setCallback($callback): IRoute
|
||||
public function setCallback($callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
|
||||
@@ -293,16 +230,16 @@ abstract class Route implements IRoute
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|callable
|
||||
* @return string
|
||||
*/
|
||||
public function getCallback()
|
||||
{
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
public function getMethod(): ?string
|
||||
public function getMethod()
|
||||
{
|
||||
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
|
||||
if (strpos($this->callback, '@') !== false) {
|
||||
$tmp = explode('@', $this->callback);
|
||||
|
||||
return $tmp[1];
|
||||
@@ -311,9 +248,9 @@ abstract class Route implements IRoute
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getClass(): ?string
|
||||
public function getClass()
|
||||
{
|
||||
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
|
||||
if (strpos($this->callback, '@') !== false) {
|
||||
$tmp = explode('@', $this->callback);
|
||||
|
||||
return $tmp[0];
|
||||
@@ -322,14 +259,14 @@ abstract class Route implements IRoute
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setMethod(string $method): IRoute
|
||||
public function setMethod($method)
|
||||
{
|
||||
$this->callback = sprintf('%s@%s', $this->getClass(), $method);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClass(string $class): IRoute
|
||||
public function setClass($class)
|
||||
{
|
||||
$this->callback = sprintf('%s@%s', $class, $this->getMethod());
|
||||
|
||||
@@ -338,9 +275,9 @@ abstract class Route implements IRoute
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setNamespace(string $namespace): IRoute
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
@@ -349,26 +286,26 @@ abstract class Route implements IRoute
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setDefaultNamespace($namespace): IRoute
|
||||
public function setDefaultNamespace($namespace)
|
||||
{
|
||||
$this->defaultNamespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultNamespace(): ?string
|
||||
public function getDefaultNamespace()
|
||||
{
|
||||
return $this->defaultNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace(): ?string
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace ?? $this->defaultNamespace;
|
||||
return ($this->namespace === null) ? $this->defaultNamespace : $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,7 +313,7 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
public function toArray()
|
||||
{
|
||||
$values = [];
|
||||
|
||||
@@ -384,22 +321,18 @@ abstract class Route implements IRoute
|
||||
$values['namespace'] = $this->namespace;
|
||||
}
|
||||
|
||||
if (\count($this->requestMethods) !== 0) {
|
||||
if (count($this->requestMethods) > 0) {
|
||||
$values['method'] = $this->requestMethods;
|
||||
}
|
||||
|
||||
if (\count($this->where) !== 0) {
|
||||
if (count($this->where) > 0) {
|
||||
$values['where'] = $this->where;
|
||||
}
|
||||
|
||||
if (\count($this->middlewares) !== 0) {
|
||||
if (count($this->middlewares) > 0) {
|
||||
$values['middleware'] = $this->middlewares;
|
||||
}
|
||||
|
||||
if ($this->defaultParameterRegex !== null) {
|
||||
$values['defaultParameterRegex'] = $this->defaultParameterRegex;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -408,35 +341,31 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @param array $values
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
public function setSettings(array $values, $merge = false)
|
||||
{
|
||||
if ($this->namespace === null && isset($values['namespace']) === true) {
|
||||
if ($this->namespace === null && isset($values['namespace'])) {
|
||||
$this->setNamespace($values['namespace']);
|
||||
}
|
||||
|
||||
if (isset($values['method']) === true) {
|
||||
if (isset($values['method'])) {
|
||||
$this->setRequestMethods(array_merge($this->requestMethods, (array)$values['method']));
|
||||
}
|
||||
|
||||
if (isset($values['where']) === true) {
|
||||
if (isset($values['where'])) {
|
||||
$this->setWhere(array_merge($this->where, (array)$values['where']));
|
||||
}
|
||||
|
||||
if (isset($values['parameters']) === true) {
|
||||
if (isset($values['parameters'])) {
|
||||
$this->setParameters(array_merge($this->parameters, (array)$values['parameters']));
|
||||
}
|
||||
|
||||
// Push middleware if multiple
|
||||
if (isset($values['middleware']) === true) {
|
||||
if (isset($values['middleware'])) {
|
||||
$this->setMiddlewares(array_merge((array)$values['middleware'], $this->middlewares));
|
||||
}
|
||||
|
||||
if (isset($values['defaultParameterRegex']) === true) {
|
||||
$this->setDefaultParameterRegex($values['defaultParameterRegex']);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -445,7 +374,7 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWhere(): array
|
||||
public function getWhere()
|
||||
{
|
||||
return $this->where;
|
||||
}
|
||||
@@ -456,7 +385,7 @@ abstract class Route implements IRoute
|
||||
* @param array $options
|
||||
* @return static
|
||||
*/
|
||||
public function setWhere(array $options): IRoute
|
||||
public function setWhere(array $options)
|
||||
{
|
||||
$this->where = $options;
|
||||
|
||||
@@ -481,12 +410,12 @@ abstract class Route implements IRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters(): array
|
||||
public function getParameters()
|
||||
{
|
||||
/* Sort the parameters after the user-defined param order, if any */
|
||||
$parameters = [];
|
||||
|
||||
if (\count($this->originalParameters) !== 0) {
|
||||
if (count($this->originalParameters) > 0) {
|
||||
$parameters = $this->originalParameters;
|
||||
}
|
||||
|
||||
@@ -497,15 +426,15 @@ abstract class Route implements IRoute
|
||||
* Get parameters
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setParameters(array $parameters): IRoute
|
||||
public function setParameters(array $parameters)
|
||||
{
|
||||
/*
|
||||
* If this is the first time setting parameters we store them so we
|
||||
* later can organize the array, in case somebody tried to sort the array.
|
||||
*/
|
||||
if (\count($parameters) !== 0 && \count($this->originalParameters) === 0) {
|
||||
if (count($parameters) > 0 && count($this->originalParameters) === 0) {
|
||||
$this->originalParameters = $parameters;
|
||||
}
|
||||
|
||||
@@ -515,10 +444,9 @@ abstract class Route implements IRoute
|
||||
}
|
||||
|
||||
/**
|
||||
* Add middleware class-name
|
||||
* Set middleware class-name
|
||||
*
|
||||
* @deprecated This method is deprecated and will be removed in the near future.
|
||||
* @param IMiddleware|string $middleware
|
||||
* @param string $middleware
|
||||
* @return static
|
||||
*/
|
||||
public function setMiddleware($middleware)
|
||||
@@ -528,26 +456,13 @@ abstract class Route implements IRoute
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add middleware class-name
|
||||
*
|
||||
* @param IMiddleware|string $middleware
|
||||
* @return static
|
||||
*/
|
||||
public function addMiddleware($middleware): IRoute
|
||||
{
|
||||
$this->middlewares[] = $middleware;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set middlewares array
|
||||
*
|
||||
* @param array $middlewares
|
||||
* @return static
|
||||
* @return $this
|
||||
*/
|
||||
public function setMiddlewares(array $middlewares): IRoute
|
||||
public function setMiddlewares(array $middlewares)
|
||||
{
|
||||
$this->middlewares = $middlewares;
|
||||
|
||||
@@ -555,35 +470,11 @@ abstract class Route implements IRoute
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @return string|array
|
||||
*/
|
||||
public function getMiddlewares(): array
|
||||
public function getMiddlewares()
|
||||
{
|
||||
return $this->middlewares;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default regular expression used when matching parameters.
|
||||
* This is used when no custom parameter regex is found.
|
||||
*
|
||||
* @param string $regex
|
||||
* @return static
|
||||
*/
|
||||
public function setDefaultParameterRegex($regex)
|
||||
{
|
||||
$this->defaultParameterRegex = $regex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default regular expression used when matching parameters.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultParameterRegex(): string
|
||||
{
|
||||
return $this->defaultParameterRegex;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
@@ -24,7 +23,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName(string $name): bool
|
||||
public function hasName($name)
|
||||
{
|
||||
if ($this->name === null) {
|
||||
return false;
|
||||
@@ -35,7 +34,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
$method = substr($name, strrpos($name, '.') + 1);
|
||||
$newName = substr($name, 0, strrpos($name, '.'));
|
||||
|
||||
if (\in_array($method, $this->names, true) === true && strtolower($this->name) === strtolower($newName)) {
|
||||
if (in_array($method, $this->names, false) === true && strtolower($this->name) === strtolower($newName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -49,12 +48,12 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
*/
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string
|
||||
public function findUrl($method = null, $parameters = null, $name = null)
|
||||
{
|
||||
if (strpos($name, '.') !== false) {
|
||||
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, false);
|
||||
if ($found !== false) {
|
||||
$method = (string)$found;
|
||||
$method = $found;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +66,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
foreach (static::$requestTypes as $requestType) {
|
||||
|
||||
if (stripos($method, $requestType) === 0) {
|
||||
$method = (string)substr($method, \strlen($requestType));
|
||||
$method = substr($method, strlen($requestType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -75,44 +74,43 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
$method .= '/';
|
||||
}
|
||||
|
||||
$group = $this->getGroup();
|
||||
|
||||
if ($group !== null && \count($group->getDomains()) !== 0) {
|
||||
$url .= '//' . $group->getDomains()[0];
|
||||
if ($this->getGroup() !== null && count($this->getGroup()->getDomains()) > 0) {
|
||||
$url .= '//' . $this->getGroup()->getDomains()[0];
|
||||
}
|
||||
|
||||
$url .= '/' . trim($this->getUrl(), '/') . '/' . strtolower($method) . implode('/', $parameters);
|
||||
$url .= '/' . trim($this->getUrl(), '/') . '/' . strtolower($method) . join('/', $parameters);
|
||||
|
||||
return '/' . trim($url, '/') . '/';
|
||||
}
|
||||
|
||||
public function matchRoute($url, Request $request): bool
|
||||
public function matchRoute(Request $request)
|
||||
{
|
||||
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
|
||||
return false;
|
||||
}
|
||||
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
|
||||
$url = rtrim($url, '/') . '/';
|
||||
|
||||
/* Match global regular-expression for route */
|
||||
$regexMatch = $this->matchRegex($request, $url);
|
||||
|
||||
if ($regexMatch === false || (stripos($url, $this->url) !== 0 && strtolower($url) !== strtolower($this->url))) {
|
||||
return false;
|
||||
if ($this->matchRegex($request, $url) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
|
||||
$path = explode('/', $strippedUrl);
|
||||
if (stripos($url, $this->url) === 0 && strtolower($url) === strtolower($this->url)) {
|
||||
|
||||
if (\count($path) !== 0) {
|
||||
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
|
||||
|
||||
$method = (isset($path[0]) === false || trim($path[0]) === '') ? $this->defaultMethod : $path[0];
|
||||
$this->method = $request->getMethod() . ucfirst($method);
|
||||
$path = explode('/', $strippedUrl);
|
||||
|
||||
$this->parameters = \array_slice($path, 1);
|
||||
if (count($path) > 0) {
|
||||
|
||||
// Set callback
|
||||
$this->setCallback($this->controller . '@' . $this->method);
|
||||
$method = (!isset($path[0]) || trim($path[0]) === '') ? $this->defaultMethod : $path[0];
|
||||
$this->method = $method;
|
||||
|
||||
return true;
|
||||
$this->parameters = array_slice($path, 1);
|
||||
|
||||
// Set callback
|
||||
$this->setCallback($this->controller . '@' . $this->method);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -123,7 +121,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getController(): string
|
||||
public function getController()
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
@@ -134,7 +132,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController(string $controller): IControllerRoute
|
||||
public function setController($controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
|
||||
@@ -144,9 +142,9 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
/**
|
||||
* Return active method
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod(): ?string
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
@@ -157,7 +155,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param string $method
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod(string $method): IRoute
|
||||
public function setMethod($method)
|
||||
{
|
||||
$this->method = $method;
|
||||
|
||||
@@ -171,9 +169,9 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
public function setSettings(array $values, $merge = false)
|
||||
{
|
||||
if (isset($values['names']) === true) {
|
||||
if (isset($values['names'])) {
|
||||
$this->names = $values['names'];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Handlers\IExceptionHandler;
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class RouteGroup extends Route implements IGroupRoute
|
||||
@@ -18,9 +16,9 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function matchDomain(Request $request): bool
|
||||
public function matchDomain(Request $request)
|
||||
{
|
||||
if ($this->domains === null || \count($this->domains) === 0) {
|
||||
if (count($this->domains) === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -28,7 +26,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
|
||||
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
|
||||
|
||||
if ($parameters !== null && \count($parameters) !== 0) {
|
||||
if ($parameters !== null && count($parameters) > 0) {
|
||||
|
||||
$this->parameters = $parameters;
|
||||
|
||||
@@ -42,44 +40,26 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
/**
|
||||
* Method called to check if route matches
|
||||
*
|
||||
* @param string $url
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function matchRoute($url, Request $request): bool
|
||||
public function matchRoute(Request $request)
|
||||
{
|
||||
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Skip if prefix doesn't match */
|
||||
if ($this->prefix !== null && stripos($url, $this->prefix) === false) {
|
||||
if ($this->prefix !== null && stripos($request->getUri(), $this->prefix) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->matchDomain($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add exception handler
|
||||
*
|
||||
* @param IExceptionHandler|string $handler
|
||||
* @return static
|
||||
*/
|
||||
public function addExceptionHandler($handler): IGroupRoute
|
||||
{
|
||||
$this->exceptionHandlers[] = $handler;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set exception-handlers for group
|
||||
*
|
||||
* @param array $handlers
|
||||
* @return static
|
||||
* @return static $this
|
||||
*/
|
||||
public function setExceptionHandlers(array $handlers): IGroupRoute
|
||||
public function setExceptionHandlers(array $handlers)
|
||||
{
|
||||
$this->exceptionHandlers = $handlers;
|
||||
|
||||
@@ -91,7 +71,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExceptionHandlers(): array
|
||||
public function getExceptionHandlers()
|
||||
{
|
||||
return $this->exceptionHandlers;
|
||||
}
|
||||
@@ -101,7 +81,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDomains(): array
|
||||
public function getDomains()
|
||||
{
|
||||
return $this->domains;
|
||||
}
|
||||
@@ -110,9 +90,9 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
* Set allowed domains for group.
|
||||
*
|
||||
* @param array $domains
|
||||
* @return static
|
||||
* @return $this
|
||||
*/
|
||||
public function setDomains(array $domains): IGroupRoute
|
||||
public function setDomains(array $domains)
|
||||
{
|
||||
$this->domains = $domains;
|
||||
|
||||
@@ -123,7 +103,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
* @param string $prefix
|
||||
* @return static
|
||||
*/
|
||||
public function setPrefix($prefix): IGroupRoute
|
||||
public function setPrefix($prefix)
|
||||
{
|
||||
$this->prefix = '/' . trim($prefix, '/');
|
||||
|
||||
@@ -133,9 +113,9 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
/**
|
||||
* Set prefix that child-routes will inherit.
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix(): ?string
|
||||
public function getPrefix()
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
@@ -147,30 +127,27 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
public function setSettings(array $values, $merge = false)
|
||||
{
|
||||
|
||||
if (isset($values['prefix']) === true) {
|
||||
if (isset($values['prefix'])) {
|
||||
$this->setPrefix($values['prefix'] . $this->prefix);
|
||||
}
|
||||
|
||||
if ($merge === false && isset($values['exceptionHandler']) === true) {
|
||||
if (isset($values['exceptionHandler'])) {
|
||||
$this->setExceptionHandlers((array)$values['exceptionHandler']);
|
||||
}
|
||||
|
||||
if ($merge === false && isset($values['domain']) === true) {
|
||||
if (isset($values['domain'])) {
|
||||
$this->setDomains((array)$values['domain']);
|
||||
}
|
||||
|
||||
if (isset($values['as']) === true) {
|
||||
|
||||
$name = $values['as'];
|
||||
|
||||
if (isset($values['as'])) {
|
||||
if ($this->name !== null && $merge !== false) {
|
||||
$name .= '.' . $this->name;
|
||||
$this->name = $values['as'] . '.' . $this->name;
|
||||
} else {
|
||||
$this->name = $values['as'];
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
parent::setSettings($values, $merge);
|
||||
@@ -183,7 +160,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
public function toArray()
|
||||
{
|
||||
$values = [];
|
||||
|
||||
@@ -195,7 +172,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
$values['as'] = $this->name;
|
||||
}
|
||||
|
||||
if (\count($this->parameters) !== 0) {
|
||||
if (count($this->parameters) > 0) {
|
||||
$values['parameters'] = $this->parameters;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute
|
||||
{
|
||||
protected $urlRegex = '/^%s\/?/u';
|
||||
|
||||
/**
|
||||
* Method called to check if route matches
|
||||
*
|
||||
* @param string $url
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function matchRoute($url, Request $request): bool
|
||||
{
|
||||
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->prefix !== null) {
|
||||
/* Parse parameters from current route */
|
||||
$parameters = $this->parseParameters($this->prefix, $url);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($parameters === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the parameters */
|
||||
$this->setParameters((array)$parameters);
|
||||
}
|
||||
|
||||
return $this->matchDomain($request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
@@ -42,7 +41,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName(string $name): bool
|
||||
public function hasName($name)
|
||||
{
|
||||
if ($this->name === null) {
|
||||
return false;
|
||||
@@ -54,17 +53,17 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
|
||||
/* Remove method/type */
|
||||
if (strpos($name, '.') !== false) {
|
||||
$name = (string)substr($name, 0, strrpos($name, '.'));
|
||||
$name = substr($name, 0, strrpos($name, '.'));
|
||||
}
|
||||
|
||||
return (strtolower($this->name) === strtolower($name));
|
||||
}
|
||||
|
||||
public function findUrl($method = null, $parameters = null, $name = null): string
|
||||
public function findUrl($method = null, $parameters = null, $name = null)
|
||||
{
|
||||
$url = array_search($name, $this->names, false);
|
||||
if ($url !== false) {
|
||||
return rtrim($this->url . $this->urls[$url], '/') . '/';
|
||||
$method = array_search($name, $this->names, false);
|
||||
if ($method !== false) {
|
||||
return rtrim($this->url . $this->urls[$method], '/') . '/';
|
||||
}
|
||||
|
||||
return $this->url;
|
||||
@@ -77,54 +76,48 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
return true;
|
||||
}
|
||||
|
||||
public function matchRoute($url, Request $request): bool
|
||||
public function matchRoute(Request $request)
|
||||
{
|
||||
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
|
||||
return false;
|
||||
}
|
||||
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
|
||||
$url = rtrim($url, '/') . '/';
|
||||
|
||||
/* Match global regular-expression for route */
|
||||
$regexMatch = $this->matchRegex($request, $url);
|
||||
|
||||
if ($regexMatch === false || (stripos($url, $this->url) !== 0 && strtolower($url) !== strtolower($this->url))) {
|
||||
return false;
|
||||
$domainMatch = $this->matchRegex($request, $url);
|
||||
if ($domainMatch !== null) {
|
||||
return $domainMatch;
|
||||
}
|
||||
|
||||
$route = rtrim($this->url, '/') . '/{id?}/{action?}';
|
||||
|
||||
/* Parse parameters from current route */
|
||||
$this->parameters = $this->parseParameters($route, $url);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($regexMatch === null && $this->parameters === null) {
|
||||
$parameters = $this->parseParameters($route, $url);
|
||||
if ($parameters === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$action = strtolower(trim($this->parameters['action']));
|
||||
$id = $this->parameters['id'];
|
||||
$this->parameters = (array)$parameters;
|
||||
|
||||
// Remove action parameter
|
||||
$action = isset($this->parameters['action']) ? $this->parameters['action'] : null;
|
||||
unset($this->parameters['action']);
|
||||
|
||||
$method = $request->getMethod();
|
||||
|
||||
// Delete
|
||||
if ($method === static::REQUEST_TYPE_DELETE && $id !== null) {
|
||||
if ($method === static::REQUEST_TYPE_DELETE && isset($this->parameters['id'])) {
|
||||
return $this->call($this->methodNames['destroy']);
|
||||
}
|
||||
|
||||
// Update
|
||||
if ($id !== null && \in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT], true) === true) {
|
||||
if (isset($this->parameters['id']) && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT], false)) {
|
||||
return $this->call($this->methodNames['update']);
|
||||
}
|
||||
|
||||
// Edit
|
||||
if ($method === static::REQUEST_TYPE_GET && $id !== null && $action === 'edit') {
|
||||
if ($method === static::REQUEST_TYPE_GET && isset($this->parameters['id']) && strtolower($action) === 'edit') {
|
||||
return $this->call($this->methodNames['edit']);
|
||||
}
|
||||
|
||||
// Create
|
||||
if ($method === static::REQUEST_TYPE_GET && $id === 'create') {
|
||||
if ($method === static::REQUEST_TYPE_GET && strtolower($action) === 'create') {
|
||||
return $this->call($this->methodNames['create']);
|
||||
}
|
||||
|
||||
@@ -134,7 +127,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
}
|
||||
|
||||
// Show
|
||||
if ($method === static::REQUEST_TYPE_GET && $id !== null) {
|
||||
if ($method === static::REQUEST_TYPE_GET && isset($this->parameters['id'])) {
|
||||
return $this->call($this->methodNames['show']);
|
||||
}
|
||||
|
||||
@@ -145,7 +138,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getController(): string
|
||||
public function getController()
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
@@ -154,14 +147,14 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param string $controller
|
||||
* @return static
|
||||
*/
|
||||
public function setController(string $controller): IControllerRoute
|
||||
public function setController($controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setName(string $name): ILoadableRoute
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
@@ -194,9 +187,9 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
/**
|
||||
* Get method names
|
||||
*
|
||||
* @return array
|
||||
* @return array $this
|
||||
*/
|
||||
public function getMethodNames(): array
|
||||
public function getMethodNames()
|
||||
{
|
||||
return $this->methodNames;
|
||||
}
|
||||
@@ -208,13 +201,13 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
* @param bool $merge
|
||||
* @return static
|
||||
*/
|
||||
public function setSettings(array $values, bool $merge = false): IRoute
|
||||
public function setSettings(array $values, $merge = false)
|
||||
{
|
||||
if (isset($values['names']) === true) {
|
||||
if (isset($values['names'])) {
|
||||
$this->names = $values['names'];
|
||||
}
|
||||
|
||||
if (isset($values['methods']) === true) {
|
||||
if (isset($values['methods'])) {
|
||||
$this->methodNames = $values['methods'];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter\Route;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
@@ -12,31 +11,27 @@ class RouteUrl extends LoadableRoute
|
||||
$this->setCallback($callback);
|
||||
}
|
||||
|
||||
public function matchRoute($url, Request $request): bool
|
||||
public function matchRoute(Request $request)
|
||||
{
|
||||
if ($this->getGroup() !== null && $this->getGroup()->matchRoute($url, $request) === false) {
|
||||
return false;
|
||||
}
|
||||
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
|
||||
$url = rtrim($url, '/') . '/';
|
||||
|
||||
/* Match global regular-expression for route */
|
||||
$regexMatch = $this->matchRegex($request, $url);
|
||||
|
||||
if ($regexMatch === false) {
|
||||
return false;
|
||||
$domainMatch = $this->matchRegex($request, $url);
|
||||
if ($domainMatch !== null) {
|
||||
return $domainMatch;
|
||||
}
|
||||
|
||||
/* Parse parameters from current route */
|
||||
/* Make regular expression based on route */
|
||||
$parameters = $this->parseParameters($this->url, $url);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($regexMatch === null && $parameters === null) {
|
||||
if ($parameters === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the parameters */
|
||||
$this->setParameters((array)$parameters);
|
||||
$this->setParameters($parameters);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+186
-354
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Pecee\SimpleRouter;
|
||||
|
||||
use Pecee\Exceptions\InvalidArgumentException;
|
||||
use Pecee\Handlers\IExceptionHandler;
|
||||
use Pecee\Http\Middleware\BaseCsrfVerifier;
|
||||
use Pecee\Http\Request;
|
||||
@@ -11,12 +9,17 @@ use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Route\IControllerRoute;
|
||||
use Pecee\SimpleRouter\Route\IGroupRoute;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
|
||||
use Pecee\SimpleRouter\Route\IRoute;
|
||||
|
||||
class Router
|
||||
{
|
||||
|
||||
/**
|
||||
* The instance of this class
|
||||
* @var static
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Current request
|
||||
* @var Request
|
||||
@@ -67,44 +70,42 @@ class Router
|
||||
protected $exceptionHandlers;
|
||||
|
||||
/**
|
||||
* List of loaded exception that has been loaded.
|
||||
* Used to ensure that exception-handlers aren't loaded twice when rewriting route.
|
||||
*
|
||||
* The current loaded route
|
||||
* @var ILoadableRoute|null
|
||||
*/
|
||||
protected $loadedRoute;
|
||||
|
||||
/**
|
||||
* List over route changes (to avoid endless-looping)
|
||||
* @var array
|
||||
*/
|
||||
protected $loadedExceptionHandlers;
|
||||
protected $routeRewrites = [];
|
||||
|
||||
/**
|
||||
* Enable or disabled debugging
|
||||
* @var bool
|
||||
* If the route has been rewritten/changed this property will contain the original url.
|
||||
* @var string
|
||||
*/
|
||||
protected $debugEnabled = false;
|
||||
protected $originalUrl;
|
||||
|
||||
/**
|
||||
* The start time used when debugging is enabled
|
||||
* @var float
|
||||
* Get current router instance
|
||||
* @return static
|
||||
*/
|
||||
protected $debugStartTime;
|
||||
public static function getInstance()
|
||||
{
|
||||
if (static::$instance === null) {
|
||||
static::$instance = new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* List containing all debug messages
|
||||
* @var array
|
||||
*/
|
||||
protected $debugList = [];
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Router constructor.
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public function __construct()
|
||||
protected function __construct()
|
||||
{
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public function reset(): void
|
||||
public function reset()
|
||||
{
|
||||
$this->processingRoute = false;
|
||||
$this->request = new Request();
|
||||
@@ -113,7 +114,6 @@ class Router
|
||||
$this->routeStack = [];
|
||||
$this->processedRoutes = [];
|
||||
$this->exceptionHandlers = [];
|
||||
$this->loadedExceptionHandlers = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,203 +121,170 @@ class Router
|
||||
* @param IRoute $route
|
||||
* @return IRoute
|
||||
*/
|
||||
public function addRoute(IRoute $route): IRoute
|
||||
public function addRoute(IRoute $route)
|
||||
{
|
||||
/*
|
||||
* If a route is currently being processed, that means that the route being added are rendered from the parent
|
||||
* routes callback, so we add them to the stack instead.
|
||||
* If a route is currently being processed, that means that the
|
||||
* route being added are rendered from the parent routes callback,
|
||||
* so we add them to the stack instead.
|
||||
*/
|
||||
if ($this->processingRoute === true) {
|
||||
$this->routeStack[] = $route;
|
||||
|
||||
return $route;
|
||||
} else {
|
||||
$this->routes[] = $route;
|
||||
}
|
||||
|
||||
$this->routes[] = $route;
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render and process any new routes added.
|
||||
*
|
||||
* @param IRoute $route
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
protected function renderAndProcess(IRoute $route): void
|
||||
{
|
||||
|
||||
$this->processingRoute = true;
|
||||
$route->renderRoute($this->request, $this);
|
||||
$this->processingRoute = false;
|
||||
|
||||
if (\count($this->routeStack) !== 0) {
|
||||
|
||||
/* Pop and grab the routes added when executing group callback earlier */
|
||||
$stack = $this->routeStack;
|
||||
$this->routeStack = [];
|
||||
|
||||
/* Route any routes added to the stack */
|
||||
$this->processRoutes($stack, $route);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process added routes.
|
||||
*
|
||||
* @param array $routes
|
||||
* @param IGroupRoute|null $group
|
||||
* @throws NotFoundHttpException
|
||||
* @param IRoute|null $parent
|
||||
*/
|
||||
protected function processRoutes(array $routes, ?IGroupRoute $group = null): void
|
||||
protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null)
|
||||
{
|
||||
$this->debug('Processing routes');
|
||||
|
||||
// Loop through each route-request
|
||||
$max = count($routes) - 1;
|
||||
|
||||
$exceptionHandlers = [];
|
||||
|
||||
// Stop processing routes if no valid route is found.
|
||||
if ($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
|
||||
$this->debug('Halted route-processing as no valid route was found');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
|
||||
|
||||
/* @var $route IRoute */
|
||||
foreach ($routes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$this->debug('Processing route "%s"', \get_class($route));
|
||||
|
||||
if ($group !== null) {
|
||||
/* Add the parent group */
|
||||
$route->setGroup($group);
|
||||
}
|
||||
$route = $routes[$i];
|
||||
|
||||
/* @var $route IGroupRoute */
|
||||
if ($route instanceof IGroupRoute) {
|
||||
|
||||
if ($route->matchRoute($url, $this->request) === true) {
|
||||
$group = $route;
|
||||
|
||||
if ($route->getCallback() !== null && is_callable($route->getCallback())) {
|
||||
|
||||
$this->processingRoute = true;
|
||||
$route->renderRoute($this->request);
|
||||
$this->processingRoute = false;
|
||||
|
||||
if ($route->matchRoute($this->request) === true) {
|
||||
|
||||
/* Add exception handlers */
|
||||
if (count($route->getExceptionHandlers()) > 0) {
|
||||
$exceptionHandlers += $route->getExceptionHandlers();
|
||||
}
|
||||
|
||||
/* Add exception handlers */
|
||||
if (\count($route->getExceptionHandlers()) !== 0) {
|
||||
/** @noinspection AdditionOperationOnArraysInspection */
|
||||
$exceptionHandlers += $route->getExceptionHandlers();
|
||||
}
|
||||
|
||||
/* Only render partial group if it matches */
|
||||
if ($route instanceof IPartialGroupRoute === true) {
|
||||
$this->renderAndProcess($route);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($route instanceof IPartialGroupRoute === false) {
|
||||
$this->renderAndProcess($route);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($route instanceof ILoadableRoute === true) {
|
||||
if ($group !== null) {
|
||||
|
||||
/* Add the parent group */
|
||||
$route->setGroup($group);
|
||||
}
|
||||
|
||||
if ($parent !== null) {
|
||||
|
||||
/* Add the parent route */
|
||||
$route->setParent($parent);
|
||||
|
||||
/* Add/merge parent settings with child */
|
||||
$route->setSettings($parent->toArray(), true);
|
||||
|
||||
}
|
||||
|
||||
if ($route instanceof ILoadableRoute) {
|
||||
|
||||
/* Add the route to the map, so we can find the active one when all routes has been loaded */
|
||||
$this->processedRoutes[] = $route;
|
||||
}
|
||||
|
||||
if (count($this->routeStack) > 0) {
|
||||
|
||||
/* Pop and grap the routes added when executing group callback earlier */
|
||||
$stack = $this->routeStack;
|
||||
$this->routeStack = [];
|
||||
|
||||
/* Route any routes added to the stack */
|
||||
$this->processRoutes($stack, $route, $group);
|
||||
}
|
||||
}
|
||||
|
||||
$this->exceptionHandlers = array_merge($exceptionHandlers, $this->exceptionHandlers);
|
||||
$this->exceptionHandlers = array_unique(array_merge($exceptionHandlers, $this->exceptionHandlers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load routes
|
||||
* @throws NotFoundHttpException
|
||||
* @return void
|
||||
*/
|
||||
public function loadRoutes(): void
|
||||
public function routeRequest($rewrite = false)
|
||||
{
|
||||
$this->debug('Loading routes');
|
||||
|
||||
/* Initialize boot-managers */
|
||||
/* @var $manager IRouterBootManager */
|
||||
foreach ($this->bootManagers as $manager) {
|
||||
$this->debug('Rendering bootmanager %s', \get_class($manager));
|
||||
$manager->boot($this->request);
|
||||
$this->debug('Finished rendering bootmanager');
|
||||
}
|
||||
|
||||
/* Loop through each route-request */
|
||||
$this->processRoutes($this->routes);
|
||||
|
||||
$this->debug('Finished loading routes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Routes the request
|
||||
*
|
||||
* @param bool $rewrite
|
||||
* @return string|null
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function routeRequest(bool $rewrite = false): ?string
|
||||
{
|
||||
$this->debug('Started routing request (rewrite: %s)', $rewrite === true ? 'yes' : 'no');
|
||||
|
||||
$methodNotAllowed = false;
|
||||
$this->loadedRoute = null;
|
||||
$routeNotAllowed = false;
|
||||
|
||||
try {
|
||||
/* Initialize boot-managers */
|
||||
if (count($this->bootManagers) > 0) {
|
||||
|
||||
$max = count($this->bootManagers) - 1;
|
||||
|
||||
/* @var $manager IRouterBootManager */
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$manager = $this->bootManagers[$i];
|
||||
|
||||
$this->request = $manager->boot($this->request);
|
||||
|
||||
if (!($this->request instanceof Request)) {
|
||||
throw new HttpException('Bootmanager "' . get_class($manager) . '" must return instance of ' . Request::class, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rewrite === false) {
|
||||
$this->loadRoutes();
|
||||
|
||||
/* Loop through each route-request */
|
||||
$this->processRoutes($this->routes);
|
||||
|
||||
if ($this->csrfVerifier !== null) {
|
||||
|
||||
/* Verify csrf token for request */
|
||||
$this->csrfVerifier->handle($this->request);
|
||||
}
|
||||
|
||||
$this->originalUrl = $this->request->getUri();
|
||||
}
|
||||
|
||||
$url = $this->request->getRewriteUrl() ?? $this->request->getUrl()->getPath();
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $key => $route) {
|
||||
/* @var $route IRoute */
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$this->debug('Matching route "%s"', \get_class($route));
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* If the route matches */
|
||||
if ($route->matchRoute($url, $this->request) === true) {
|
||||
if ($route->matchRoute($this->request) === true) {
|
||||
|
||||
/* Check if request method matches */
|
||||
if (\count($route->getRequestMethods()) !== 0 && \in_array($this->request->getMethod(), $route->getRequestMethods(), true) === false) {
|
||||
$this->debug('Method "%s" not allowed', $this->request->getMethod());
|
||||
$methodNotAllowed = true;
|
||||
if (count($route->getRequestMethods()) > 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), false) === false) {
|
||||
$routeNotAllowed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$route->loadMiddleware($this->request, $this);
|
||||
$this->loadedRoute = $route;
|
||||
$this->loadedRoute->loadMiddleware($this->request, $this->loadedRoute);
|
||||
|
||||
$output = $this->handleRouteRewrite($key, $url);
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
/* If the request has changed, we reinitialize the router */
|
||||
if ($this->request->getUri() !== $this->originalUrl && in_array($this->request->getUri(), $this->routeRewrites) === false) {
|
||||
$this->routeRewrites[] = $this->request->getUri();
|
||||
$this->routeRequest(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Render route */
|
||||
$methodNotAllowed = false;
|
||||
$routeNotAllowed = false;
|
||||
$this->request->setUri($this->originalUrl);
|
||||
$this->loadedRoute->renderRoute($this->request);
|
||||
|
||||
$this->request->addLoadedRoute($route);
|
||||
|
||||
$output = $route->renderRoute($this->request, $this);
|
||||
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$output = $this->handleRouteRewrite($key, $url);
|
||||
if ($output !== null) {
|
||||
return $output;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,117 +292,52 @@ class Router
|
||||
$this->handleException($e);
|
||||
}
|
||||
|
||||
if ($methodNotAllowed === true) {
|
||||
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUrl()->getPath(), $this->request->getMethod());
|
||||
$this->handleException(new HttpException($message, 403));
|
||||
if ($routeNotAllowed === true) {
|
||||
$this->handleException(new HttpException('Route or method not allowed', 403));
|
||||
}
|
||||
|
||||
if (\count($this->request->getLoadedRoutes()) === 0) {
|
||||
|
||||
$rewriteUrl = $this->request->getRewriteUrl();
|
||||
|
||||
if ($rewriteUrl !== null) {
|
||||
$message = sprintf('Route not found: "%s" (rewrite from: "%s")', $rewriteUrl, $this->request->getUrl()->getPath());
|
||||
} else {
|
||||
$message = sprintf('Route not found: "%s"', $this->request->getUrl()->getPath());
|
||||
}
|
||||
|
||||
$this->debug($message);
|
||||
|
||||
return $this->handleException(new NotFoundHttpException($message, 404));
|
||||
if ($this->loadedRoute === null) {
|
||||
$this->handleException(new NotFoundHttpException('Route not found: ' . $this->request->getUri(), 404));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle route-rewrite
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $url
|
||||
* @return string|null
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function handleRouteRewrite($key, string $url): ?string
|
||||
protected function handleException(\Exception $e)
|
||||
{
|
||||
/* If the request has changed */
|
||||
if ($this->request->hasRewrite() === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$route = $this->request->getRewriteRoute();
|
||||
|
||||
if ($route !== null) {
|
||||
/* Add rewrite route */
|
||||
$this->processedRoutes[] = $route;
|
||||
}
|
||||
|
||||
if ($this->request->getRewriteUrl() !== $url) {
|
||||
unset($this->processedRoutes[$key]);
|
||||
$this->request->setHasRewrite(false);
|
||||
|
||||
return $this->routeRequest(true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Exception $e
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
* @return string|null
|
||||
*/
|
||||
protected function handleException(\Exception $e): ?string
|
||||
{
|
||||
$this->debug('Starting exception handling for "%s"', \get_class($e));
|
||||
$max = count($this->exceptionHandlers);
|
||||
|
||||
/* @var $handler IExceptionHandler */
|
||||
foreach ($this->exceptionHandlers as $key => $handler) {
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
|
||||
if (\is_object($handler) === false) {
|
||||
$handler = new $handler();
|
||||
}
|
||||
$handler = $this->exceptionHandlers[$i];
|
||||
|
||||
$this->debug('Processing exception-handler "%s"', \get_class($handler));
|
||||
$handler = new $handler();
|
||||
|
||||
if (($handler instanceof IExceptionHandler) === false) {
|
||||
if (!($handler instanceof IExceptionHandler)) {
|
||||
throw new HttpException('Exception handler must implement the IExceptionHandler interface.', 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$request = $handler->handleError($this->request, $this->loadedRoute, $e);
|
||||
|
||||
$this->debug('Start rendering exception handler');
|
||||
$handler->handleError($this->request, $e);
|
||||
$this->debug('Finished rendering exception-handler');
|
||||
|
||||
if (isset($this->loadedExceptionHandlers[$key]) === false && $this->request->hasRewrite() === true) {
|
||||
$this->loadedExceptionHandlers[$key] = $handler;
|
||||
|
||||
$this->debug('Exception handler contains rewrite, reloading routes');
|
||||
|
||||
return $this->routeRequest(true);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
/* If the request has changed */
|
||||
if ($request !== null && $this->request->getUri() !== $this->originalUrl && in_array($request->getUri(), $this->routeRewrites) === false) {
|
||||
$this->request = $request;
|
||||
$this->routeRewrites[] = $request->getUri();
|
||||
$this->routeRequest(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->debug('Finished processing');
|
||||
}
|
||||
|
||||
$this->debug('Finished exception handling - exception not handled, throwing');
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function arrayToParams(array $getParams = [], bool $includeEmpty = true): string
|
||||
public function arrayToParams(array $getParams = [], $includeEmpty = true)
|
||||
{
|
||||
if (\count($getParams) !== 0) {
|
||||
if (count($getParams) > 0) {
|
||||
|
||||
if ($includeEmpty === false) {
|
||||
$getParams = array_filter($getParams, function ($item) {
|
||||
return (trim($item) !== '');
|
||||
return (!empty($item));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -451,60 +353,49 @@ class Router
|
||||
* @param string $name
|
||||
* @return ILoadableRoute|null
|
||||
*/
|
||||
public function findRoute(string $name): ?ILoadableRoute
|
||||
public function findRoute($name)
|
||||
{
|
||||
|
||||
$this->debug('Finding route by name "%s"', $name);
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
|
||||
if ($route->hasName($name) === true) {
|
||||
$this->debug('Found route "%s" by name "%s"', $route->getUrl(), $name);
|
||||
|
||||
if ($route->hasName($name)) {
|
||||
return $route;
|
||||
}
|
||||
|
||||
/* Direct match to controller */
|
||||
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($name)) {
|
||||
$this->debug('Found route "%s" by controller "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/* Using @ is most definitely a controller@method or alias@method */
|
||||
if (\is_string($name) === true && strpos($name, '@') !== false) {
|
||||
[$controller, $method] = array_map('strtolower', explode('@', $name));
|
||||
if (strpos($name, '@') !== false) {
|
||||
list($controller, $method) = array_map('strtolower', explode('@', $name));
|
||||
|
||||
if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) {
|
||||
$this->debug('Found route "%s" by controller "%s" and method "%s"', $route->getUrl(), $controller, $method);
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if callback matches (if it's not a function) */
|
||||
if (\is_string($name) === true && \is_string($route->getCallback()) && strpos($name, '@') !== false && strpos($route->getCallback(), '@') !== false && \is_callable($route->getCallback()) === false) {
|
||||
if (strpos($name, '@') !== false && strpos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) {
|
||||
|
||||
/* Check if the entire callback is matching */
|
||||
if (strpos($route->getCallback(), $name) === 0 || strtolower($route->getCallback()) === strtolower($name)) {
|
||||
$this->debug('Found route "%s" by callback "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/* Check if the class part of the callback matches (class@method) */
|
||||
if (strtolower($name) === strtolower($route->getClass())) {
|
||||
$this->debug('Found route "%s" by class "%s"', $route->getUrl(), $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->debug('Route not found');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -523,19 +414,13 @@ class Router
|
||||
* @param string|null $name
|
||||
* @param string|array|null $parameters
|
||||
* @param array|null $getParams
|
||||
* @throws InvalidArgumentException
|
||||
* @throws \InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(?string $name = null, $parameters = null, $getParams = null): string
|
||||
public function getUrl($name = null, $parameters = null, $getParams = null)
|
||||
{
|
||||
$this->debug('Finding url', \func_get_args());
|
||||
|
||||
if ($getParams !== null && \is_array($getParams) === false) {
|
||||
throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
||||
}
|
||||
|
||||
if ($name === '' && $parameters === '') {
|
||||
return '/';
|
||||
if ($getParams !== null && is_array($getParams) === false) {
|
||||
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
||||
}
|
||||
|
||||
/* Only merge $_GET when all parameters are null */
|
||||
@@ -547,14 +432,14 @@ class Router
|
||||
|
||||
/* Return current route if no options has been specified */
|
||||
if ($name === null && $parameters === null) {
|
||||
return $this->request->getUrl()->getPath() . $this->arrayToParams($getParams);
|
||||
$url = rtrim(parse_url($this->request->getUri(), PHP_URL_PATH), '/');
|
||||
|
||||
return (($url === '') ? '/' : $url . '/') . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
$loadedRoute = $this->request->getLoadedRoute();
|
||||
|
||||
/* If nothing is defined and a route is loaded we use that */
|
||||
if ($name === null && $loadedRoute !== null) {
|
||||
return $loadedRoute->findUrl($loadedRoute->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
|
||||
if ($name === null && $this->loadedRoute !== null) {
|
||||
return $this->loadedRoute->findUrl($this->loadedRoute->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
/* We try to find a match on the given name */
|
||||
@@ -565,16 +450,20 @@ class Router
|
||||
}
|
||||
|
||||
/* Using @ is most definitely a controller@method or alias@method */
|
||||
if (\is_string($name) === true && strpos($name, '@') !== false) {
|
||||
[$controller, $method] = explode('@', $name);
|
||||
if (strpos($name, '@') !== false) {
|
||||
list($controller, $method) = explode('@', $name);
|
||||
|
||||
/* Loop through all the routes to see if we can find a match */
|
||||
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* Check if the route contains the name/alias */
|
||||
if ($route->hasName($controller) === true) {
|
||||
if ($route->hasName($controller)) {
|
||||
return $route->findUrl($method, $parameters, $name) . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
@@ -587,75 +476,52 @@ class Router
|
||||
}
|
||||
|
||||
/* No result so we assume that someone is using a hardcoded url and join everything together. */
|
||||
$url = trim(implode('/', array_merge((array)$name, (array)$parameters)), '/');
|
||||
$url = trim(join('/', array_merge((array)$name, (array)$parameters)), '/');
|
||||
|
||||
return (($url === '') ? '/' : '/' . $url . '/') . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BootManagers
|
||||
* Get bootmanagers
|
||||
* @return array
|
||||
*/
|
||||
public function getBootManagers(): array
|
||||
public function getBootManagers()
|
||||
{
|
||||
return $this->bootManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set BootManagers
|
||||
* Set bootmanagers
|
||||
* @param array $bootManagers
|
||||
*/
|
||||
public function setBootManagers(array $bootManagers): void
|
||||
public function setBootManagers(array $bootManagers)
|
||||
{
|
||||
$this->bootManagers = $bootManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BootManager
|
||||
* Add bootmanager
|
||||
* @param IRouterBootManager $bootManager
|
||||
*/
|
||||
public function addBootManager(IRouterBootManager $bootManager): void
|
||||
public function addBootManager(IRouterBootManager $bootManager)
|
||||
{
|
||||
$this->bootManagers[] = $bootManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get routes that has been processed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProcessedRoutes(): array
|
||||
{
|
||||
return $this->processedRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRoutes(): array
|
||||
public function getRoutes()
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set routes
|
||||
*
|
||||
* @param array $routes
|
||||
* @return static
|
||||
*/
|
||||
public function setRoutes(array $routes): self
|
||||
{
|
||||
$this->routes = $routes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current request
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
public function getRequest(): Request
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
@@ -664,7 +530,7 @@ class Router
|
||||
* Get csrf verifier class
|
||||
* @return BaseCsrfVerifier
|
||||
*/
|
||||
public function getCsrfVerifier(): ?BaseCsrfVerifier
|
||||
public function getCsrfVerifier()
|
||||
{
|
||||
return $this->csrfVerifier;
|
||||
}
|
||||
@@ -683,46 +549,12 @@ class Router
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new debug message
|
||||
* @param string $message
|
||||
* @param array $args
|
||||
* Get loaded route
|
||||
* @return ILoadableRoute|null
|
||||
*/
|
||||
public function debug(string $message, ...$args): void
|
||||
public function getLoadedRoute()
|
||||
{
|
||||
if ($this->debugEnabled === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
$this->debugList[] = [
|
||||
'message' => vsprintf($message, $args),
|
||||
'time' => number_format(microtime(true) - $this->debugStartTime, 10),
|
||||
'trace' => end($trace),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disables debugging
|
||||
*
|
||||
* @param bool $boolean
|
||||
*/
|
||||
public function setDebugEnabled(bool $boolean): void
|
||||
{
|
||||
if ($boolean === true) {
|
||||
$this->debugStartTime = microtime(true);
|
||||
}
|
||||
|
||||
$this->debugEnabled = $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list containing all debug messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDebugLog(): array
|
||||
{
|
||||
return $this->debugList;
|
||||
return $this->loadedRoute;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,21 +7,15 @@
|
||||
* This class is added so calls can be made statically like Router::get() making the code look pretty.
|
||||
* It also adds some extra functionality like default-namespace.
|
||||
*/
|
||||
|
||||
namespace Pecee\SimpleRouter;
|
||||
|
||||
use Pecee\Exceptions\InvalidArgumentException;
|
||||
use Pecee\Handlers\CallbackExceptionHandler;
|
||||
use Pecee\Http\Middleware\BaseCsrfVerifier;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\Http\Response;
|
||||
use Pecee\SimpleRouter\Exceptions\HttpException;
|
||||
use Pecee\SimpleRouter\Route\IGroupRoute;
|
||||
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
|
||||
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Route\IRoute;
|
||||
use Pecee\SimpleRouter\Route\RouteController;
|
||||
use Pecee\SimpleRouter\Route\RouteGroup;
|
||||
use Pecee\SimpleRouter\Route\RoutePartialGroup;
|
||||
use Pecee\SimpleRouter\Route\RouteResource;
|
||||
use Pecee\SimpleRouter\Route\RouteUrl;
|
||||
|
||||
@@ -29,7 +23,7 @@ class SimpleRouter
|
||||
{
|
||||
/**
|
||||
* Default namespace added to all routes
|
||||
* @var string|null
|
||||
* @var string
|
||||
*/
|
||||
protected static $defaultNamespace;
|
||||
|
||||
@@ -40,74 +34,14 @@ class SimpleRouter
|
||||
protected static $response;
|
||||
|
||||
/**
|
||||
* Router instance
|
||||
* @var Router
|
||||
*/
|
||||
protected static $router;
|
||||
|
||||
/**
|
||||
* Start routing
|
||||
* Start/route request
|
||||
*
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
public static function start(): void
|
||||
public static function start()
|
||||
{
|
||||
echo static::router()->routeRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the routing an return array with debugging-information
|
||||
*
|
||||
* @return array
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function startDebug(): array
|
||||
{
|
||||
$routerOutput = null;
|
||||
|
||||
try {
|
||||
ob_start();
|
||||
static::router()->setDebugEnabled(true);
|
||||
static::start();
|
||||
$routerOutput = ob_get_contents();
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
// Try to parse library version
|
||||
$composerFile = \dirname(__DIR__, 3) . '/composer.lock';
|
||||
$version = false;
|
||||
|
||||
if (is_file($composerFile) === true) {
|
||||
$composerInfo = json_decode(file_get_contents($composerFile), true);
|
||||
|
||||
if (isset($composerInfo['packages']) === true && \is_array($composerInfo['packages']) === true) {
|
||||
foreach ($composerInfo['packages'] as $package) {
|
||||
if (isset($package['name']) === true && strtolower($package['name']) === 'pecee/simple-router') {
|
||||
$version = $package['version'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'url' => static::request()->getUrl(),
|
||||
'method' => static::request()->getMethod(),
|
||||
'host' => static::request()->getHost(),
|
||||
'loaded_routes' => static::request()->getLoadedRoutes(),
|
||||
'all_routes' => static::router()->getRoutes(),
|
||||
'boot_managers' => static::router()->getBootManagers(),
|
||||
'csrf_verifier' => static::router()->getCsrfVerifier(),
|
||||
'log' => static::router()->getDebugLog(),
|
||||
'router_output' => $routerOutput,
|
||||
'library_version' => $version,
|
||||
'php_version' => PHP_VERSION,
|
||||
'server_params' => static::request()->getHeaders(),
|
||||
];
|
||||
static::router()->routeRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +49,7 @@ class SimpleRouter
|
||||
*
|
||||
* @param string $defaultNamespace
|
||||
*/
|
||||
public static function setDefaultNamespace(string $defaultNamespace): void
|
||||
public static function setDefaultNamespace($defaultNamespace)
|
||||
{
|
||||
static::$defaultNamespace = $defaultNamespace;
|
||||
}
|
||||
@@ -124,9 +58,8 @@ class SimpleRouter
|
||||
* Base CSRF verifier
|
||||
*
|
||||
* @param BaseCsrfVerifier $baseCsrfVerifier
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier): void
|
||||
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier)
|
||||
{
|
||||
static::router()->setCsrfVerifier($baseCsrfVerifier);
|
||||
}
|
||||
@@ -136,9 +69,8 @@ class SimpleRouter
|
||||
* Perfect if you want to load pretty-urls from a file or database.
|
||||
*
|
||||
* @param IRouterBootManager $bootManager
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function addBootManager(IRouterBootManager $bootManager): void
|
||||
public static function addBootManager(IRouterBootManager $bootManager)
|
||||
{
|
||||
static::router()->addBootManager($bootManager);
|
||||
}
|
||||
@@ -149,11 +81,9 @@ class SimpleRouter
|
||||
* @param string $url
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
*
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function get(string $url, $callback, array $settings = null): IRoute
|
||||
public static function get($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['get'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -165,9 +95,8 @@ class SimpleRouter
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function post(string $url, $callback, array $settings = null): IRoute
|
||||
public static function post($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['post'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -179,9 +108,8 @@ class SimpleRouter
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function put(string $url, $callback, array $settings = null): IRoute
|
||||
public static function put($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['put'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -193,9 +121,8 @@ class SimpleRouter
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function patch(string $url, $callback, array $settings = null): IRoute
|
||||
public static function patch($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['patch'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -207,9 +134,8 @@ class SimpleRouter
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function options(string $url, $callback, array $settings = null): IRoute
|
||||
public static function options($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['options'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -221,9 +147,8 @@ class SimpleRouter
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function delete(string $url, $callback, array $settings = null): IRoute
|
||||
public static function delete($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['delete'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -233,48 +158,19 @@ class SimpleRouter
|
||||
*
|
||||
* @param array $settings
|
||||
* @param \Closure $callback
|
||||
* @throws \InvalidArgumentException
|
||||
* @return RouteGroup
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function group(array $settings = [], \Closure $callback): IGroupRoute
|
||||
public static function group(array $settings = [], \Closure $callback)
|
||||
{
|
||||
if (\is_callable($callback) === false) {
|
||||
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
||||
}
|
||||
|
||||
$group = new RouteGroup();
|
||||
$group->setCallback($callback);
|
||||
$group->setSettings($settings);
|
||||
|
||||
static::router()->addRoute($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special group that has the same benefits as group but supports
|
||||
* parameters and which are only rendered when the url matches.
|
||||
*
|
||||
* @param string $url
|
||||
* @param \Closure $callback
|
||||
* @param array $settings
|
||||
* @return RoutePartialGroup
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function partialGroup(string $url, \Closure $callback, array $settings = []): IPartialGroupRoute
|
||||
{
|
||||
if (\is_callable($callback) === false) {
|
||||
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
||||
if (is_callable($callback) === false) {
|
||||
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
||||
}
|
||||
|
||||
$settings['prefix'] = $url;
|
||||
|
||||
$group = new RoutePartialGroup();
|
||||
$group->setSettings($settings);
|
||||
$group->setCallback($callback);
|
||||
|
||||
static::router()->addRoute($group);
|
||||
|
||||
return $group;
|
||||
@@ -288,9 +184,8 @@ class SimpleRouter
|
||||
* @param array|null $settings
|
||||
* @see SimpleRouter::form
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function basic(string $url, $callback, array $settings = null): IRoute
|
||||
public static function basic($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['get', 'post'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -304,9 +199,8 @@ class SimpleRouter
|
||||
* @param array|null $settings
|
||||
* @see SimpleRouter::form
|
||||
* @return RouteUrl
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function form(string $url, $callback, array $settings = null): IRoute
|
||||
public static function form($url, $callback, array $settings = null)
|
||||
{
|
||||
return static::match(['get', 'post'], $url, $callback, $settings);
|
||||
}
|
||||
@@ -318,10 +212,9 @@ class SimpleRouter
|
||||
* @param string $url
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl|IRoute
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @return RouteUrl
|
||||
*/
|
||||
public static function match(array $requestMethods, string $url, $callback, array $settings = null)
|
||||
public static function match(array $requestMethods, $url, $callback, array $settings = null)
|
||||
{
|
||||
$route = new RouteUrl($url, $callback);
|
||||
$route->setRequestMethods($requestMethods);
|
||||
@@ -342,10 +235,9 @@ class SimpleRouter
|
||||
* @param string $url
|
||||
* @param string|\Closure $callback
|
||||
* @param array|null $settings
|
||||
* @return RouteUrl|IRoute
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @return RouteUrl
|
||||
*/
|
||||
public static function all(string $url, $callback, array $settings = null)
|
||||
public static function all($url, $callback, array $settings = null)
|
||||
{
|
||||
$route = new RouteUrl($url, $callback);
|
||||
$route = static::addDefaultNamespace($route);
|
||||
@@ -365,10 +257,9 @@ class SimpleRouter
|
||||
* @param string $url
|
||||
* @param string $controller
|
||||
* @param array|null $settings
|
||||
* @return RouteController|IRoute
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @return RouteController
|
||||
*/
|
||||
public static function controller(string $url, $controller, array $settings = null)
|
||||
public static function controller($url, $controller, array $settings = null)
|
||||
{
|
||||
$route = new RouteController($url, $controller);
|
||||
$route = static::addDefaultNamespace($route);
|
||||
@@ -388,13 +279,11 @@ class SimpleRouter
|
||||
* @param string $url
|
||||
* @param string $controller
|
||||
* @param array|null $settings
|
||||
* @return RouteResource|IRoute
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
* @return RouteResource
|
||||
*/
|
||||
public static function resource(string $url, $controller, array $settings = null)
|
||||
public static function resource($url, $controller, array $settings = null)
|
||||
{
|
||||
$route = new RouteResource($url, $controller);
|
||||
$route = static::addDefaultNamespace($route);
|
||||
|
||||
if ($settings !== null) {
|
||||
$route->setSettings($settings);
|
||||
@@ -405,29 +294,6 @@ class SimpleRouter
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add exception callback handler.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return CallbackExceptionHandler $callbackHandler
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function error(\Closure $callback): CallbackExceptionHandler
|
||||
{
|
||||
$routes = static::router()->getRoutes();
|
||||
|
||||
$callbackHandler = new CallbackExceptionHandler($callback);
|
||||
|
||||
$group = new RouteGroup();
|
||||
$group->addExceptionHandler($callbackHandler);
|
||||
|
||||
array_unshift($routes, $group);
|
||||
|
||||
static::router()->setRoutes($routes);
|
||||
|
||||
return $callbackHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url for a route by using either name/alias, class or method name.
|
||||
*
|
||||
@@ -443,11 +309,10 @@ class SimpleRouter
|
||||
* @param string|null $name
|
||||
* @param string|array|null $parameters
|
||||
* @param array|null $getParams
|
||||
* @throws \Pecee\Exceptions\InvalidArgumentException
|
||||
* @throws \Exception
|
||||
* @return string
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function getUrl(?string $name = null, $parameters = null, $getParams = null): string
|
||||
public static function getUrl($name = null, $parameters = null, $getParams = null)
|
||||
{
|
||||
return static::router()->getUrl($name, $parameters, $getParams);
|
||||
}
|
||||
@@ -456,9 +321,8 @@ class SimpleRouter
|
||||
* Get the request
|
||||
*
|
||||
* @return \Pecee\Http\Request
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function request(): Request
|
||||
public static function request()
|
||||
{
|
||||
return static::router()->getRequest();
|
||||
}
|
||||
@@ -467,9 +331,8 @@ class SimpleRouter
|
||||
* Get the response object
|
||||
*
|
||||
* @return Response
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function response(): Response
|
||||
public static function response()
|
||||
{
|
||||
if (static::$response === null) {
|
||||
static::$response = new Response(static::request());
|
||||
@@ -482,15 +345,10 @@ class SimpleRouter
|
||||
* Returns the router instance
|
||||
*
|
||||
* @return Router
|
||||
* @throws \Pecee\Http\Exceptions\MalformedUrlException
|
||||
*/
|
||||
public static function router(): Router
|
||||
public static function router()
|
||||
{
|
||||
if (static::$router === null) {
|
||||
static::$router = new Router();
|
||||
}
|
||||
|
||||
return static::$router;
|
||||
return Router::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,38 +357,19 @@ class SimpleRouter
|
||||
* @param IRoute $route
|
||||
* @return IRoute
|
||||
*/
|
||||
public static function addDefaultNamespace(IRoute $route): IRoute
|
||||
protected static function addDefaultNamespace(IRoute $route)
|
||||
{
|
||||
if (static::$defaultNamespace !== null) {
|
||||
$namespace = static::$defaultNamespace;
|
||||
|
||||
$callback = $route->getCallback();
|
||||
|
||||
/* Only add default namespace on relative callbacks */
|
||||
if ($callback === null || (\is_string($callback) === true && $callback[0] !== '\\')) {
|
||||
|
||||
$namespace = static::$defaultNamespace;
|
||||
|
||||
$currentNamespace = $route->getNamespace();
|
||||
|
||||
if ($currentNamespace !== null) {
|
||||
$namespace .= '\\' . $currentNamespace;
|
||||
}
|
||||
|
||||
$route->setDefaultNamespace($namespace);
|
||||
|
||||
if ($route->getNamespace() !== null) {
|
||||
$namespace .= '\\' . $route->getNamespace();
|
||||
}
|
||||
|
||||
$route->setDefaultNamespace($namespace);
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default namespace
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getDefaultNamespace(): ?string
|
||||
{
|
||||
return static::$defaultNamespace;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
class DummyController
|
||||
{
|
||||
public function start()
|
||||
{
|
||||
echo static::class . '@' . 'start() OK';
|
||||
}
|
||||
|
||||
public function param($params = null)
|
||||
{
|
||||
$params = func_get_args();
|
||||
echo 'Params: ' . join(', ', $params);
|
||||
}
|
||||
|
||||
public function notFound()
|
||||
{
|
||||
echo 'not found';
|
||||
}
|
||||
|
||||
public function silent() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
require_once 'Exceptions/MiddlewareLoadedException.php';
|
||||
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class DummyMiddleware implements IMiddleware
|
||||
{
|
||||
public function handle(Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route)
|
||||
{
|
||||
throw new MiddlewareLoadedException('Middleware loaded!');
|
||||
}
|
||||
|
||||
}
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandlerException extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandler implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route = null, \Exception $error)
|
||||
{
|
||||
echo $error->getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class TestExceptionHandlerFirst implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route = null, \Exception $error)
|
||||
{
|
||||
echo 'ExceptionHandler 1 loaded' . chr(10);
|
||||
|
||||
$request->setUri('/');
|
||||
return $request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class TestExceptionHandlerSecond implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route = null, \Exception $error)
|
||||
{
|
||||
echo 'ExceptionHandler 2 loaded' . chr(10);
|
||||
|
||||
$request->setUri('/');
|
||||
return $request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
class TestExceptionHandlerThird implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route = null, \Exception $error)
|
||||
{
|
||||
echo 'ExceptionHandler 3 loaded' . chr(10);
|
||||
|
||||
throw new ExceptionHandlerException('All good!', 666);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
|
||||
use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
|
||||
|
||||
class GroupTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $result;
|
||||
|
||||
public function testGroupLoad()
|
||||
{
|
||||
$this->result = false;
|
||||
|
||||
SimpleRouter::group(['prefix' => '/group'], function () {
|
||||
$this->result = true;
|
||||
});
|
||||
|
||||
try {
|
||||
SimpleRouter::start();
|
||||
} catch (Exception $e) {
|
||||
// ignore RouteNotFound exception
|
||||
}
|
||||
|
||||
$this->assertTrue($this->result);
|
||||
}
|
||||
|
||||
public function testNestedGroup()
|
||||
{
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/api/v1/test');
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
|
||||
SimpleRouter::group(['prefix' => '/api'], function () {
|
||||
|
||||
SimpleRouter::group(['prefix' => '/v1'], function () {
|
||||
SimpleRouter::get('/test', 'DummyController@start');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testManyRoutes()
|
||||
{
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/match');
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
|
||||
SimpleRouter::group(['prefix' => '/api'], function () {
|
||||
|
||||
SimpleRouter::group(['prefix' => '/v1'], function () {
|
||||
SimpleRouter::get('/test', 'DummyController@start');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::get('/my/match', 'DummyController@start');
|
||||
|
||||
SimpleRouter::group(['prefix' => '/service'], function () {
|
||||
|
||||
SimpleRouter::group(['prefix' => '/v1'], function () {
|
||||
SimpleRouter::get('/no-match', 'DummyController@start');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testUrls()
|
||||
{
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/fancy/url/1');
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
|
||||
// Test array name
|
||||
SimpleRouter::get('/my/fancy/url/1', 'DummyController@start', ['as' => 'fancy1']);
|
||||
|
||||
// Test method name
|
||||
SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setName('fancy2');
|
||||
|
||||
SimpleRouter::start();
|
||||
|
||||
$this->assertEquals('/my/fancy/url/1/', SimpleRouter::getUrl('fancy1'));
|
||||
$this->assertEquals('/my/fancy/url/2/', SimpleRouter::getUrl('fancy2'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||
|
||||
use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
|
||||
|
||||
class MiddlewareTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testMiddlewareFound()
|
||||
{
|
||||
$this->setExpectedException('MiddlewareLoadedException');
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
|
||||
SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () {
|
||||
SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']);
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testNestedMiddlewareLoad()
|
||||
{
|
||||
$this->setExpectedException('MiddlewareLoadedException');
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
|
||||
SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler', 'middleware' => 'DummyMiddleware'], function () {
|
||||
SimpleRouter::get('/my/test/url', 'DummyController@start');
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Exceptions/ExceptionHandlerException.php';
|
||||
require_once 'Dummy/Handler/TestExceptionHandlerFirst.php';
|
||||
require_once 'Dummy/Handler/TestExceptionHandlerSecond.php';
|
||||
require_once 'Dummy/Handler/TestExceptionHandlerThird.php';
|
||||
|
||||
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException as NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
|
||||
|
||||
class RouterRouteTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $result = false;
|
||||
|
||||
public function testMultiParam()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/test-param1-param2');
|
||||
|
||||
SimpleRouter::get('/test-{param1}-{param2}', function($param1, $param2) {
|
||||
|
||||
if($param1 === 'param1' && $param2 === 'param2') {
|
||||
$this->result = true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
|
||||
$this->assertTrue($this->result);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to another route through 3 exception handlers.
|
||||
*
|
||||
* You will see "ExceptionHandler 1 loaded" 2 times. This happen because
|
||||
* the exceptionhandler is asking the router to reload.
|
||||
*
|
||||
* That means that the exceptionhandler is loaded again, but this time
|
||||
* the router ignores the same rewrite-route to avoid loop - loads
|
||||
* the second which have same behavior and is also ignored before
|
||||
* throwing the final Exception in ExceptionHandler 3.
|
||||
*
|
||||
* So this tests:
|
||||
* 1. If ExceptionHandlers loads
|
||||
* 2. If ExceptionHandlers load in the correct order
|
||||
* 3. If ExceptionHandlers can rewrite the page on error
|
||||
* 4. If the router can avoid redirect-loop due to developer has started loop.
|
||||
* 5. And finally if we reaches the last exception-handler and that the correct
|
||||
* exception-type is being thrown.
|
||||
*/
|
||||
public function testNotFound()
|
||||
{
|
||||
$this->setExpectedException('ExceptionHandlerException');
|
||||
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/test-param1-param2');
|
||||
|
||||
SimpleRouter::group(['exceptionHandler' => ['TestExceptionHandlerFirst', 'TestExceptionHandlerSecond']], function () {
|
||||
|
||||
SimpleRouter::group(['exceptionHandler' => 'TestExceptionHandlerThird'], function () {
|
||||
|
||||
SimpleRouter::get('/non-existing-path', 'DummyController@start');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
|
||||
SimpleRouter::get('/my/test/url', 'DummyController@start');
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testPost()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
SimpleRouter::request()->setMethod('post');
|
||||
|
||||
SimpleRouter::post('/my/test/url', 'DummyController@start');
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testPut()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
SimpleRouter::request()->setMethod('put');
|
||||
|
||||
SimpleRouter::put('/my/test/url', 'DummyController@start');
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
SimpleRouter::request()->setMethod('delete');
|
||||
|
||||
SimpleRouter::delete('/my/test/url', 'DummyController@start');
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testMethodNotAllowed()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setUri('/my/test/url');
|
||||
SimpleRouter::request()->setMethod('post');
|
||||
|
||||
SimpleRouter::get('/my/test/url', 'DummyController@start');
|
||||
|
||||
try {
|
||||
SimpleRouter::start();
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals(403, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function testSimpleParam()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/test-param1');
|
||||
|
||||
SimpleRouter::get('/test-{param1}', 'DummyController@param');
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testPathParamRegex()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/test/path/123123');
|
||||
|
||||
SimpleRouter::get('/test/path/{myParam}', 'DummyController@param', ['where' => ['myParam' => '([0-9]+)']]);
|
||||
SimpleRouter::start();
|
||||
}
|
||||
|
||||
public function testDomainRoute()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/test');
|
||||
SimpleRouter::request()->setHost('hello.world.com');
|
||||
|
||||
$this->result = false;
|
||||
|
||||
SimpleRouter::group(['domain' => '{subdomain}.world.com'], function () {
|
||||
SimpleRouter::get('/test', function ($subdomain = null) {
|
||||
$this->result = ($subdomain === 'hello');
|
||||
});
|
||||
});
|
||||
|
||||
SimpleRouter::start();
|
||||
|
||||
$this->assertTrue($this->result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||
|
||||
use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
|
||||
|
||||
class RouterUrlTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $result = false;
|
||||
|
||||
protected function getUrl($name = null, $parameters = null, array $getParams = [])
|
||||
{
|
||||
return SimpleRouter::getUrl($name, $parameters, $getParams);
|
||||
}
|
||||
|
||||
public function testUrls()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/');
|
||||
|
||||
// Match normal route on alias
|
||||
SimpleRouter::get('/', 'DummyController@silent', ['as' => 'home']);
|
||||
|
||||
SimpleRouter::get('/about', 'DummyController@about');
|
||||
|
||||
SimpleRouter::group(['prefix' => '/admin', 'as' => 'admin'], function () {
|
||||
|
||||
// Match route with prefix on alias
|
||||
SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'home']);
|
||||
|
||||
// Match controller with prefix and alias
|
||||
SimpleRouter::controller('/users', 'DummyController', ['as' => 'users']);
|
||||
|
||||
// Match controller with prefix and NO alias
|
||||
SimpleRouter::controller('/pages', 'DummyController');
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::group(['prefix' => 'api', 'as' => 'api'], function () {
|
||||
|
||||
// Match resource controller
|
||||
SimpleRouter::resource('phones', 'DummyController');
|
||||
|
||||
});
|
||||
|
||||
SimpleRouter::controller('gadgets', 'DummyController', ['names' => ['getIphoneInfo' => 'iphone']]);
|
||||
|
||||
// Match controller with no prefix and no alias
|
||||
SimpleRouter::controller('/cats', 'CatsController');
|
||||
|
||||
// Pretend to load page
|
||||
SimpleRouter::start();
|
||||
|
||||
$this->assertEquals('/gadgets/iphoneinfo/', $this->getUrl('gadgets.iphone'));
|
||||
|
||||
$this->assertEquals('/api/phones/create/', $this->getUrl('api.phones.create'));
|
||||
|
||||
// Should match /
|
||||
$this->assertEquals('/', $this->getUrl('home'));
|
||||
|
||||
// Should match /about/
|
||||
$this->assertEquals('/about/', $this->getUrl('DummyController@about'));
|
||||
|
||||
// Should match /admin/
|
||||
$this->assertEquals('/admin/', $this->getUrl('DummyController@start'));
|
||||
|
||||
// Should match /admin/
|
||||
$this->assertEquals('/admin/', $this->getUrl('admin.home'));
|
||||
|
||||
// Should match /admin/2/
|
||||
$this->assertEquals('/admin/2/', $this->getUrl('admin.home', ['id' => 2]));
|
||||
|
||||
// Should match /admin/users/
|
||||
$this->assertEquals('/admin/users/', $this->getUrl('admin.users'));
|
||||
|
||||
// Should match /admin/users/home/
|
||||
$this->assertEquals('/admin/users/home/', $this->getUrl('admin.users@home'));
|
||||
|
||||
// Should match /cats/
|
||||
$this->assertEquals('/cats/', $this->getUrl('CatsController'));
|
||||
|
||||
// Should match /cats/view/
|
||||
$this->assertEquals('/cats/view/', $this->getUrl('CatsController', 'view'));
|
||||
|
||||
// Should match /cats/view/
|
||||
//$this->assertEquals('/cats/view/', $this->getUrl('CatsController', ['view']));
|
||||
|
||||
// Should match /cats/view/666
|
||||
$this->assertEquals('/cats/view/666/', $this->getUrl('CatsController@getView', ['666']));
|
||||
|
||||
// Should match /funny/man/
|
||||
$this->assertEquals('/funny/man/', $this->getUrl('/funny/man'));
|
||||
|
||||
// Should match /?jackdaniels=true&cola=yeah
|
||||
$this->assertEquals('/?jackdaniels=true&cola=yeah', $this->getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah']));
|
||||
|
||||
}
|
||||
|
||||
public function testRegEx()
|
||||
{
|
||||
SimpleRouter::router()->reset();
|
||||
SimpleRouter::request()->setMethod('get');
|
||||
SimpleRouter::request()->setUri('/my/custom-path');
|
||||
|
||||
SimpleRouter::get('/my/{path}', 'DummyController@start')->where(['path' => '[a-zA-Z\-]+']);
|
||||
|
||||
SimpleRouter::start();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
class DummyController
|
||||
{
|
||||
public function method1()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function method2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function param($params = null)
|
||||
{
|
||||
echo join(', ', func_get_args());
|
||||
}
|
||||
|
||||
public function getTest()
|
||||
{
|
||||
echo 'getTest';
|
||||
}
|
||||
|
||||
public function postTest()
|
||||
{
|
||||
echo 'postTest';
|
||||
}
|
||||
|
||||
public function putTest()
|
||||
{
|
||||
echo 'putTest';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
require_once 'Exception/MiddlewareLoadedException.php';
|
||||
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class DummyMiddleware implements \Pecee\Http\Middleware\IMiddleware
|
||||
{
|
||||
public function handle(Request $request) : void
|
||||
{
|
||||
throw new MiddlewareLoadedException('Middleware loaded!');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ResponseException extends \Exception
|
||||
{
|
||||
protected $response;
|
||||
|
||||
public function __construct($response)
|
||||
{
|
||||
$this->response = $response;
|
||||
parent::__construct('', 0);
|
||||
}
|
||||
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandler implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
|
||||
{
|
||||
echo $error->getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandlerFirst implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
|
||||
{
|
||||
global $stack;
|
||||
$stack[] = static::class;
|
||||
|
||||
$request->setUrl('/');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandlerSecond implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
|
||||
{
|
||||
global $stack;
|
||||
$stack[] = static::class;
|
||||
|
||||
$request->setUrl('/');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ExceptionHandlerThird implements \Pecee\Handlers\IExceptionHandler
|
||||
{
|
||||
public function handleError(\Pecee\Http\Request $request, \Exception $error) : void
|
||||
{
|
||||
global $stack;
|
||||
$stack[] = static::class;
|
||||
|
||||
throw new ResponseException('ExceptionHandler loaded');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
|
||||
class RewriteMiddleware implements IMiddleware {
|
||||
|
||||
public function handle(Request $request) : void {
|
||||
|
||||
$request->setRewriteCallback(function() {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
class ResourceController implements \Pecee\Controllers\IResourceController
|
||||
{
|
||||
|
||||
public function index() : ?string
|
||||
{
|
||||
echo 'index';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function show($id) : ?string
|
||||
{
|
||||
echo 'show ' . $id;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function store() : ?string
|
||||
{
|
||||
echo 'store';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function create() : ?string
|
||||
{
|
||||
echo 'create';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function edit($id) : ?string
|
||||
{
|
||||
echo 'edit ' . $id;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function update($id) : ?string
|
||||
{
|
||||
echo 'update ' . $id;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function destroy($id) : ?string
|
||||
{
|
||||
echo 'destroy ' . $id;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
|
||||
class GroupTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $result;
|
||||
|
||||
public function testGroupLoad()
|
||||
{
|
||||
$this->result = false;
|
||||
|
||||
TestRouter::group(['prefix' => '/group'], function () {
|
||||
$this->result = true;
|
||||
});
|
||||
|
||||
try {
|
||||
TestRouter::debug('/', 'get');
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
$this->assertTrue($this->result);
|
||||
}
|
||||
|
||||
public function testNestedGroup()
|
||||
{
|
||||
|
||||
TestRouter::group(['prefix' => '/api'], function () {
|
||||
|
||||
TestRouter::group(['prefix' => '/v1'], function () {
|
||||
TestRouter::get('/test', 'DummyController@method1');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
TestRouter::debug('/api/v1/test', 'get');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testMultipleRoutes()
|
||||
{
|
||||
|
||||
TestRouter::group(['prefix' => '/api'], function () {
|
||||
|
||||
TestRouter::group(['prefix' => '/v1'], function () {
|
||||
TestRouter::get('/test', 'DummyController@method1');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
TestRouter::get('/my/match', 'DummyController@method1');
|
||||
|
||||
TestRouter::group(['prefix' => '/service'], function () {
|
||||
|
||||
TestRouter::group(['prefix' => '/v1'], function () {
|
||||
TestRouter::get('/no-match', 'DummyController@method1');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
TestRouter::debug('/my/match', 'get');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testUrls()
|
||||
{
|
||||
// Test array name
|
||||
TestRouter::get('/my/fancy/url/1', 'DummyController@method1', ['as' => 'fancy1']);
|
||||
|
||||
// Test method name
|
||||
TestRouter::get('/my/fancy/url/2', 'DummyController@method1')->setName('fancy2');
|
||||
|
||||
TestRouter::debugNoReset('/my/fancy/url/1');
|
||||
|
||||
$this->assertEquals('/my/fancy/url/1/', TestRouter::getUrl('fancy1'));
|
||||
$this->assertEquals('/my/fancy/url/2/', TestRouter::getUrl('fancy2'));
|
||||
|
||||
TestRouter::router()->reset();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||
|
||||
class MiddlewareTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testMiddlewareFound()
|
||||
{
|
||||
$this->expectException(MiddlewareLoadedException::class);
|
||||
|
||||
TestRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () {
|
||||
TestRouter::get('/my/test/url', 'DummyController@method1', ['middleware' => 'DummyMiddleware']);
|
||||
});
|
||||
|
||||
TestRouter::debug('/my/test/url', 'get');
|
||||
|
||||
}
|
||||
|
||||
public function testNestedMiddlewareDontLoad()
|
||||
{
|
||||
|
||||
TestRouter::group(['exceptionHandler' => 'ExceptionHandler', 'middleware' => 'DummyMiddleware'], function () {
|
||||
TestRouter::get('/middleware', 'DummyController@method1');
|
||||
});
|
||||
|
||||
TestRouter::get('/my/test/url', 'DummyController@method1');
|
||||
|
||||
TestRouter::debug('/my/test/url', 'get');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Exception/ExceptionHandlerException.php';
|
||||
|
||||
class RouterCallbackExceptionHandlerTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function testCallbackExceptionHandler()
|
||||
{
|
||||
$this->expectException(ExceptionHandlerException::class);
|
||||
|
||||
// Match normal route on alias
|
||||
TestRouter::get('/my-new-url', 'DummyController@method2');
|
||||
TestRouter::get('/my-url', 'DummyController@method1');
|
||||
|
||||
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $exception) {
|
||||
throw new ExceptionHandlerException();
|
||||
});
|
||||
|
||||
TestRouter::debugNoReset('/404-url', 'get');
|
||||
TestRouter::router()->reset();
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyController.php';
|
||||
|
||||
class RouterControllerTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
// Match normal route on alias
|
||||
TestRouter::controller('/url', 'DummyController');
|
||||
|
||||
$response = TestRouter::debugOutput('/url/test', 'get');
|
||||
|
||||
$this->assertEquals('getTest', $response);
|
||||
|
||||
}
|
||||
|
||||
public function testPost()
|
||||
{
|
||||
// Match normal route on alias
|
||||
TestRouter::controller('/url', 'DummyController');
|
||||
|
||||
$response = TestRouter::debugOutput('/url/test', 'post');
|
||||
|
||||
$this->assertEquals('postTest', $response);
|
||||
|
||||
}
|
||||
|
||||
public function testPut()
|
||||
{
|
||||
// Match normal route on alias
|
||||
TestRouter::controller('/url', 'DummyController');
|
||||
|
||||
$response = TestRouter::debugOutput('/url/test', 'put');
|
||||
|
||||
$this->assertEquals('putTest', $response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||
|
||||
class RouterPartialGroupTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function testParameters()
|
||||
{
|
||||
$result1 = null;
|
||||
$result2 = null;
|
||||
|
||||
TestRouter::partialGroup('{param1}/{param2}', function ($param1 = null, $param2 = null) use (&$result1, &$result2) {
|
||||
$result1 = $param1;
|
||||
$result2 = $param2;
|
||||
|
||||
TestRouter::get('/', 'DummyController@method1');
|
||||
});
|
||||
|
||||
TestRouter::debug('/param1/param2', 'get');
|
||||
|
||||
$this->assertEquals('param1', $result1);
|
||||
$this->assertEquals('param2', $result2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/ResourceController.php';
|
||||
|
||||
class RouterResourceTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function testResourceStore()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource', 'post');
|
||||
|
||||
$this->assertEquals('store', $response);
|
||||
}
|
||||
|
||||
public function testResourceCreate()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource/create', 'get');
|
||||
|
||||
$this->assertEquals('create', $response);
|
||||
|
||||
}
|
||||
|
||||
public function testResourceIndex()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource', 'get');
|
||||
|
||||
$this->assertEquals('index', $response);
|
||||
}
|
||||
|
||||
public function testResourceDestroy()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource/38', 'delete');
|
||||
|
||||
$this->assertEquals('destroy 38', $response);
|
||||
}
|
||||
|
||||
|
||||
public function testResourceEdit()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource/38/edit', 'get');
|
||||
|
||||
$this->assertEquals('edit 38', $response);
|
||||
|
||||
}
|
||||
|
||||
public function testResourceUpdate()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource/38', 'put');
|
||||
|
||||
$this->assertEquals('update 38', $response);
|
||||
|
||||
}
|
||||
|
||||
public function testResourceGet()
|
||||
{
|
||||
TestRouter::resource('/resource', 'ResourceController');
|
||||
$response = TestRouter::debugOutput('/resource/38', 'get');
|
||||
|
||||
$this->assertEquals('show 38', $response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
<?php
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Exception/ResponseException.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandlerFirst.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandlerSecond.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandlerThird.php';
|
||||
require_once 'Dummy/Middleware/RewriteMiddleware.php';
|
||||
|
||||
class RouteRewriteTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Redirects to another route through 3 exception handlers.
|
||||
*
|
||||
* You will see "ExceptionHandler 1 loaded" 2 times. This happen because
|
||||
* the exceptionhandler is asking the router to reload.
|
||||
*
|
||||
* That means that the exceptionhandler is loaded again, but this time
|
||||
* the router ignores the same rewrite-route to avoid loop - loads
|
||||
* the second which have same behavior and is also ignored before
|
||||
* throwing the final Exception in ExceptionHandler 3.
|
||||
*
|
||||
* So this tests:
|
||||
* 1. If ExceptionHandlers loads
|
||||
* 2. If ExceptionHandlers load in the correct order
|
||||
* 3. If ExceptionHandlers can rewrite the page on error
|
||||
* 4. If the router can avoid redirect-loop due to developer has started loop.
|
||||
* 5. And finally if we reaches the last exception-handler and that the correct
|
||||
* exception-type is being thrown.
|
||||
*/
|
||||
public function testExceptionHandlerRewrite()
|
||||
{
|
||||
global $stack;
|
||||
$stack = [];
|
||||
|
||||
TestRouter::group(['exceptionHandler' => [ExceptionHandlerFirst::class, ExceptionHandlerSecond::class]], function () use ($stack) {
|
||||
|
||||
TestRouter::group(['exceptionHandler' => ExceptionHandlerThird::class], function () use ($stack) {
|
||||
|
||||
TestRouter::get('/my-path', 'DummyController@method1');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
TestRouter::debug('/my-non-existing-path', 'get');
|
||||
} catch (\ResponseException $e) {
|
||||
|
||||
}
|
||||
|
||||
$expectedStack = [
|
||||
ExceptionHandlerFirst::class,
|
||||
ExceptionHandlerSecond::class,
|
||||
ExceptionHandlerThird::class,
|
||||
];
|
||||
|
||||
$this->assertEquals($expectedStack, $stack);
|
||||
|
||||
}
|
||||
|
||||
public function testRewriteExceptionMessage()
|
||||
{
|
||||
$this->expectException(\Pecee\SimpleRouter\Exceptions\NotFoundHttpException::class);
|
||||
|
||||
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) {
|
||||
|
||||
if (strtolower($request->getUrl()->getPath()) === '/my/test/') {
|
||||
$request->setRewriteUrl('/another-non-existing');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
TestRouter::debug('/my/test', 'get');
|
||||
}
|
||||
|
||||
public function testRewriteUrlFromRoute()
|
||||
{
|
||||
|
||||
TestRouter::get('/old', function () {
|
||||
TestRouter::request()->setRewriteUrl('/new');
|
||||
});
|
||||
|
||||
TestRouter::get('/new', function () {
|
||||
echo 'ok';
|
||||
});
|
||||
|
||||
TestRouter::get('/new1', function () {
|
||||
echo 'ok';
|
||||
});
|
||||
|
||||
TestRouter::get('/new2', function () {
|
||||
echo 'ok';
|
||||
});
|
||||
|
||||
$output = TestRouter::debugOutput('/old');
|
||||
|
||||
$this->assertEquals('ok', $output);
|
||||
|
||||
}
|
||||
|
||||
public function testRewriteCallbackFromRoute()
|
||||
{
|
||||
|
||||
TestRouter::get('/old', function () {
|
||||
TestRouter::request()->setRewriteUrl('/new');
|
||||
});
|
||||
|
||||
TestRouter::get('/new', function () {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
TestRouter::get('/new1', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
TestRouter::get('/new/2', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
$output = TestRouter::debugOutput('/old');
|
||||
|
||||
TestRouter::router()->reset();
|
||||
|
||||
$this->assertEquals('ok', $output);
|
||||
|
||||
}
|
||||
|
||||
public function testRewriteRouteFromRoute()
|
||||
{
|
||||
|
||||
TestRouter::get('/match', function () {
|
||||
TestRouter::request()->setRewriteRoute(new \Pecee\SimpleRouter\Route\RouteUrl('/match', function () {
|
||||
return 'ok';
|
||||
}));
|
||||
});
|
||||
|
||||
TestRouter::get('/old1', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
TestRouter::get('/old/2', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
TestRouter::get('/new2', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
$output = TestRouter::debugOutput('/match');
|
||||
|
||||
TestRouter::router()->reset();
|
||||
|
||||
$this->assertEquals('ok', $output);
|
||||
|
||||
}
|
||||
|
||||
public function testMiddlewareRewrite()
|
||||
{
|
||||
|
||||
TestRouter::group(['middleware' => 'RewriteMiddleware'], function () {
|
||||
TestRouter::get('/', function () {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
TestRouter::get('no/match', function () {
|
||||
return 'fail';
|
||||
});
|
||||
});
|
||||
|
||||
$output = TestRouter::debugOutput('/');
|
||||
|
||||
$this->assertEquals('ok', $output);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Exception/ExceptionHandlerException.php';
|
||||
|
||||
class RouterRouteTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $result = false;
|
||||
|
||||
public function testMultiParam()
|
||||
{
|
||||
TestRouter::get('/test-{param1}-{param2}', function ($param1, $param2) {
|
||||
|
||||
if ($param1 === 'param1' && $param2 === 'param2') {
|
||||
$this->result = true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
TestRouter::debug('/test-param1-param2', 'get');
|
||||
|
||||
$this->assertTrue($this->result);
|
||||
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
{
|
||||
$this->expectException('\Pecee\SimpleRouter\Exceptions\NotFoundHttpException');
|
||||
TestRouter::get('/non-existing-path', 'DummyController@method1');
|
||||
TestRouter::debug('/test-param1-param2', 'post');
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
TestRouter::get('/my/test/url', 'DummyController@method1');
|
||||
TestRouter::debug('/my/test/url', 'get');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testPost()
|
||||
{
|
||||
TestRouter::post('/my/test/url', 'DummyController@method1');
|
||||
TestRouter::debug('/my/test/url', 'post');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testPut()
|
||||
{
|
||||
TestRouter::put('/my/test/url', 'DummyController@method1');
|
||||
TestRouter::debug('/my/test/url', 'put');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
TestRouter::delete('/my/test/url', 'DummyController@method1');
|
||||
TestRouter::debug('/my/test/url', 'delete');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testMethodNotAllowed()
|
||||
{
|
||||
TestRouter::get('/my/test/url', 'DummyController@method1');
|
||||
|
||||
try {
|
||||
TestRouter::debug('/my/test/url', 'post');
|
||||
} catch (\Exception $e) {
|
||||
$this->assertEquals(403, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function testSimpleParam()
|
||||
{
|
||||
TestRouter::get('/test-{param1}', 'DummyController@param');
|
||||
$response = TestRouter::debugOutput('/test-param1', 'get');
|
||||
|
||||
$this->assertEquals('param1', $response);
|
||||
}
|
||||
|
||||
public function testPathParamRegex()
|
||||
{
|
||||
TestRouter::get('/{lang}/productscategories/{name}', 'DummyController@param', ['where' => ['lang' => '[a-z]+', 'name' => '[A-Za-z0-9\-]+']]);
|
||||
$response = TestRouter::debugOutput('/it/productscategories/system', 'get');
|
||||
|
||||
$this->assertEquals('it, system', $response);
|
||||
}
|
||||
|
||||
public function testDomainAllowedRoute()
|
||||
{
|
||||
$this->result = false;
|
||||
|
||||
TestRouter::group(['domain' => '{subdomain}.world.com'], function () {
|
||||
TestRouter::get('/test', function ($subdomain = null) {
|
||||
$this->result = ($subdomain === 'hello');
|
||||
});
|
||||
});
|
||||
|
||||
TestRouter::request()->setHost('hello.world.com');
|
||||
TestRouter::debug('/test', 'get');
|
||||
|
||||
$this->assertTrue($this->result);
|
||||
|
||||
}
|
||||
|
||||
public function testDomainNotAllowedRoute()
|
||||
{
|
||||
$this->result = false;
|
||||
|
||||
TestRouter::group(['domain' => '{subdomain}.world.com'], function () {
|
||||
TestRouter::get('/test', function ($subdomain = null) {
|
||||
$this->result = ($subdomain === 'hello');
|
||||
});
|
||||
});
|
||||
|
||||
TestRouter::request()->setHost('other.world.com');
|
||||
|
||||
|
||||
TestRouter::debug('/test', 'get');
|
||||
|
||||
$this->assertFalse($this->result);
|
||||
|
||||
}
|
||||
|
||||
public function testRegEx()
|
||||
{
|
||||
TestRouter::get('/my/{path}', 'DummyController@method1')->where(['path' => '[a-zA-Z\-]+']);
|
||||
TestRouter::debug('/my/custom-path', 'get');
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testParameterDefaultValue() {
|
||||
|
||||
$defaultVariable = null;
|
||||
|
||||
TestRouter::get('/my/{path?}', function($path = 'working') use(&$defaultVariable) {
|
||||
$defaultVariable = $path;
|
||||
});
|
||||
|
||||
TestRouter::debug('/my/');
|
||||
|
||||
$this->assertEquals('working', $defaultVariable);
|
||||
|
||||
}
|
||||
|
||||
public function testDefaultParameterRegex()
|
||||
{
|
||||
TestRouter::get('/my/{path}', 'DummyController@param', ['defaultParameterRegex' => '[\w\-]+']);
|
||||
$output = TestRouter::debugOutput('/my/custom-regex', 'get');
|
||||
|
||||
$this->assertEquals('custom-regex', $output);
|
||||
}
|
||||
|
||||
public function testDefaultParameterRegexGroup()
|
||||
{
|
||||
TestRouter::group(['defaultParameterRegex' => '[\w\-]+'], function() {
|
||||
TestRouter::get('/my/{path}', 'DummyController@param');
|
||||
});
|
||||
|
||||
$output = TestRouter::debugOutput('/my/custom-regex', 'get');
|
||||
|
||||
$this->assertEquals('custom-regex', $output);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'Dummy/DummyMiddleware.php';
|
||||
require_once 'Dummy/DummyController.php';
|
||||
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||
|
||||
class RouterUrlTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function testIssue253()
|
||||
{
|
||||
TestRouter::get('/', 'DummyController@method1');
|
||||
TestRouter::get('/page/{id?}', 'DummyController@method1');
|
||||
TestRouter::get('/test-output', function() {
|
||||
return 'return value';
|
||||
});
|
||||
|
||||
TestRouter::debugNoReset('/page/22', 'get');
|
||||
$this->assertEquals('/page/{id?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/', 'get');
|
||||
$this->assertEquals('/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
$output = TestRouter::debugOutput('/test-output', 'get');
|
||||
$this->assertEquals('return value', $output);
|
||||
|
||||
TestRouter::router()->reset();
|
||||
}
|
||||
|
||||
public function testUnicodeCharacters()
|
||||
{
|
||||
// Test spanish characters
|
||||
TestRouter::get('/cursos/listado/{listado?}/{category?}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-]+']);
|
||||
TestRouter::get('/test/{param}', 'DummyController@method1', ['defaultParameterRegex' => '[\w\p{L}\s-\í]+']);
|
||||
TestRouter::debugNoReset('/cursos/listado/especialidad/cirugía local', 'get');
|
||||
|
||||
$this->assertEquals('/cursos/listado/{listado?}/{category?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/test/Dermatología');
|
||||
$parameters = TestRouter::request()->getLoadedRoute()->getParameters();
|
||||
|
||||
$this->assertEquals('Dermatología', $parameters['param']);
|
||||
|
||||
// Test danish characters
|
||||
TestRouter::get('/kategori/økse', 'DummyController@method1', ['defaultParameterRegex' => '[\w\ø]+']);
|
||||
TestRouter::debugNoReset('/kategori/økse', 'get');
|
||||
|
||||
$this->assertEquals('/kategori/økse/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::router()->reset();
|
||||
}
|
||||
|
||||
public function testOptionalParameters()
|
||||
{
|
||||
TestRouter::get('/aviso/legal', 'DummyController@method1');
|
||||
TestRouter::get('/aviso/{aviso}', 'DummyController@method1');
|
||||
TestRouter::get('/pagina/{pagina}', 'DummyController@method1');
|
||||
TestRouter::get('/{pagina?}', 'DummyController@method1');
|
||||
|
||||
TestRouter::debugNoReset('/aviso/optional', 'get');
|
||||
$this->assertEquals('/aviso/{aviso}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/pagina/optional', 'get');
|
||||
$this->assertEquals('/pagina/{pagina}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/optional', 'get');
|
||||
$this->assertEquals('/{pagina?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/avisolegal', 'get');
|
||||
$this->assertNotEquals('/aviso/{aviso}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::debugNoReset('/avisolegal', 'get');
|
||||
$this->assertEquals('/{pagina?}/', TestRouter::router()->getRequest()->getLoadedRoute()->getUrl());
|
||||
|
||||
TestRouter::router()->reset();
|
||||
}
|
||||
|
||||
public function testSimilarUrls()
|
||||
{
|
||||
// Match normal route on alias
|
||||
TestRouter::resource('/url11', 'DummyController@method1');
|
||||
TestRouter::resource('/url1', 'DummyController@method1', ['as' => 'match']);
|
||||
|
||||
TestRouter::debugNoReset('/url1', 'get');
|
||||
|
||||
$this->assertEquals(TestRouter::getUrl('match'), TestRouter::getUrl());
|
||||
|
||||
TestRouter::router()->reset();
|
||||
}
|
||||
|
||||
public function testUrls()
|
||||
{
|
||||
// Match normal route on alias
|
||||
TestRouter::get('/', 'DummyController@method1', ['as' => 'home']);
|
||||
|
||||
TestRouter::get('/about', 'DummyController@about');
|
||||
|
||||
TestRouter::group(['prefix' => '/admin', 'as' => 'admin'], function () {
|
||||
|
||||
// Match route with prefix on alias
|
||||
TestRouter::get('/{id?}', 'DummyController@method2', ['as' => 'home']);
|
||||
|
||||
// Match controller with prefix and alias
|
||||
TestRouter::controller('/users', 'DummyController', ['as' => 'users']);
|
||||
|
||||
// Match controller with prefix and NO alias
|
||||
TestRouter::controller('/pages', 'DummyController');
|
||||
|
||||
});
|
||||
|
||||
TestRouter::group(['prefix' => 'api', 'as' => 'api'], function () {
|
||||
|
||||
// Match resource controller
|
||||
TestRouter::resource('phones', 'DummyController');
|
||||
|
||||
});
|
||||
|
||||
TestRouter::controller('gadgets', 'DummyController', ['names' => ['getIphoneInfo' => 'iphone']]);
|
||||
|
||||
// Match controller with no prefix and no alias
|
||||
TestRouter::controller('/cats', 'CatsController');
|
||||
|
||||
// Pretend to load page
|
||||
TestRouter::debugNoReset('/', 'get');
|
||||
|
||||
$this->assertEquals('/gadgets/iphoneinfo/', TestRouter::getUrl('gadgets.iphone'));
|
||||
|
||||
$this->assertEquals('/api/phones/create/', TestRouter::getUrl('api.phones.create'));
|
||||
|
||||
// Should match /
|
||||
$this->assertEquals('/', TestRouter::getUrl('home'));
|
||||
|
||||
// Should match /about/
|
||||
$this->assertEquals('/about/', TestRouter::getUrl('DummyController@about'));
|
||||
|
||||
// Should match /admin/
|
||||
$this->assertEquals('/admin/', TestRouter::getUrl('DummyController@method2'));
|
||||
|
||||
// Should match /admin/
|
||||
$this->assertEquals('/admin/', TestRouter::getUrl('admin.home'));
|
||||
|
||||
// Should match /admin/2/
|
||||
$this->assertEquals('/admin/2/', TestRouter::getUrl('admin.home', ['id' => 2]));
|
||||
|
||||
// Should match /admin/users/
|
||||
$this->assertEquals('/admin/users/', TestRouter::getUrl('admin.users'));
|
||||
|
||||
// Should match /admin/users/home/
|
||||
$this->assertEquals('/admin/users/home/', TestRouter::getUrl('admin.users@home'));
|
||||
|
||||
// Should match /cats/
|
||||
$this->assertEquals('/cats/', TestRouter::getUrl('CatsController'));
|
||||
|
||||
// Should match /cats/view/
|
||||
$this->assertEquals('/cats/view/', TestRouter::getUrl('CatsController', 'view'));
|
||||
|
||||
// Should match /cats/view/
|
||||
//$this->assertEquals('/cats/view/', TestRouter::getUrl('CatsController', ['view']));
|
||||
|
||||
// Should match /cats/view/666
|
||||
$this->assertEquals('/cats/view/666/', TestRouter::getUrl('CatsController@getView', ['666']));
|
||||
|
||||
// Should match /funny/man/
|
||||
$this->assertEquals('/funny/man/', TestRouter::getUrl('/funny/man'));
|
||||
|
||||
// Should match /?jackdaniels=true&cola=yeah
|
||||
$this->assertEquals('/?jackdaniels=true&cola=yeah', TestRouter::getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah']));
|
||||
|
||||
TestRouter::router()->reset();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
|
||||
{
|
||||
|
||||
public static function debugNoReset($testUrl, $testMethod = 'get')
|
||||
{
|
||||
static::request()->setUrl($testUrl);
|
||||
static::request()->setMethod($testMethod);
|
||||
|
||||
static::start();
|
||||
}
|
||||
|
||||
public static function debug($testUrl, $testMethod = 'get')
|
||||
{
|
||||
try {
|
||||
static::debugNoReset($testUrl, $testMethod);
|
||||
} catch(\Exception $e) {
|
||||
static::router()->reset();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
static::router()->reset();
|
||||
|
||||
}
|
||||
|
||||
public static function debugOutput($testUrl, $testMethod = 'get')
|
||||
{
|
||||
$response = null;
|
||||
|
||||
// Route request
|
||||
ob_start();
|
||||
static::debug($testUrl, $testMethod);
|
||||
$response = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Return response
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require_once 'TestRouter.php';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use \Pecee\SimpleRouter\SimpleRouter;
|
||||
|
||||
SimpleRouter::get('/user/{name}', 'UserController@show')->where(['name' => '[\w]+']);
|
||||
$debugInfo = SimpleRouter::startDebug();
|
||||
echo sprintf('<pre>%s</pre>', var_export($debugInfo, true));
|
||||
exit;
|
||||
Reference in New Issue
Block a user