Development

- Fixed updatae causing middlewares to sometimes load on wrong routes.
- Converted project to PSR/2.
- Updated InputCollection class and added get method for easy access to values.
- Complete refactor of RouterBase.
- Added findRoute method to RouterBase.
- It's now possible to change parameter modifiers and symbol by overwriting properties on RouterBase.
- Added RouterUrlTest unit-test for testing route-urls.
- Added IRestController that can be easily implemented in custom ResourceController-classes.
- It's now possible to use "-" instead of "_" when using getHeader method in Request class.
- Added PHPDocs.
- Fixed "/" route sometimes returning "//" as url.
- Optimisations and bugfixes.
This commit is contained in:
Simon Sessingø
2016-11-19 02:48:19 +01:00
parent a4447313f6
commit ed1ac74e7a
41 changed files with 2813 additions and 2318 deletions
+13 -9
View File
@@ -29,8 +29,8 @@ The goal of this project is to create a router that is 100% compatible with the
- CSRF protection. - CSRF protection.
- Optional parameters - Optional parameters
- Sub-domain routing - Sub-domain routing
- Custom boot managers to redirect urls to other routes - Custom boot managers to rewrite urls to "nicer" ones.
- Input manager; to manage `GET`, `POST` params. - Input manager; easily manage `GET`, `POST` and `FILE` values.
## Installation and demo ## Installation and demo
@@ -71,6 +71,7 @@ This router is heavily inspired by the Laravel 5.* router, so anything you find
- ExceptionsHandlers must implement the `IExceptionHandler` interface. - ExceptionsHandlers must implement the `IExceptionHandler` interface.
- Middlewares must implement the `IMiddleware` interface. - Middlewares must implement the `IMiddleware` interface.
- Resource controllers can inherit the `IRestController` interface, but is not required.
```php ```php
use Pecee\SimpleRouter\SimpleRouter; use Pecee\SimpleRouter\SimpleRouter;
@@ -103,7 +104,7 @@ SimpleRouter::group(['prefix' => '/v1', 'middleware' => '\MyWebsite\Middleware\S
*/ */
SimpleRouter::all('/ajax', 'ControllerAjax@process')->match('.*?\\/ajax\\/([A-Za-z0-9\\/]+)'); SimpleRouter::all('/ajax', 'ControllerAjax@process')->match('.*?\\/ajax\\/([A-Za-z0-9\\/]+)');
// Restful resource // Restful resource (see IRestController interface for available methods)
SimpleRouter::resource('/rest', 'ControllerRessource'); SimpleRouter::resource('/rest', 'ControllerRessource');
// Load the entire controller (where url matches method names - getIndex(), postIndex() etc) // Load the entire controller (where url matches method names - getIndex(), postIndex() etc)
@@ -146,11 +147,10 @@ class CustomExceptionHandler implements IExceptionHandler {
// Output error as json if on api path. // Output error as json if on api path.
if(stripos($request->getUri(), '/api') !== false) { if(stripos($request->getUri(), '/api') !== false) {
response()->json(['error' => $error->getMessage()]); response()->json([ 'error' => $error->getMessage() ]);
} }
// Otherwise default exception will be thrown by the router. // Otherwise default exception will be thrown by the router.
} }
} }
@@ -210,7 +210,7 @@ class Router extends SimpleRouter {
require_once 'routes.php'; require_once 'routes.php';
// change default namespace for all routes // change default namespace for all routes
parent::setDefaultNamespace('\Demo\Controllers'); parent::setDefaultNamespace('\Demo');
// Do initial stuff // Do initial stuff
parent::start(); parent::start();
@@ -449,6 +449,12 @@ $object = input()->getObject('name');
$object = input()->get->name; $object = input()->get->name;
$object = input()->post->name; $object = input()->post->name;
$object = input()->file->name; $object = input()->file->name;
// -- or --
$object = input()->get->get($key, $defaultValue);
$object = input()->post->get($key, $defaultValue);
$object = input()->file->get($key, $defaultValue);
``` ```
**Return all parameters:** **Return all parameters:**
@@ -464,6 +470,7 @@ $values = input()->all([
``` ```
All object inherits from `InputItem` class and will always contain these methods: All object inherits from `InputItem` class and will always contain these methods:
- `getValue()` - returns the value of the input. - `getValue()` - returns the value of the input.
- `getIndex()` - returns the index/key of the input. - `getIndex()` - returns the index/key of the input.
- `getName()` - returns a human friendly name for the input (company_name will be Company Name etc). - `getName()` - returns a human friendly name for the input (company_name will be Company Name etc).
@@ -476,9 +483,6 @@ All object inherits from `InputItem` class and will always contain these methods
- `getType()` - get mime-type for file. - `getType()` - get mime-type for file.
- `getError()` - get file upload error. - `getError()` - get file upload error.
### Easy access to methods
Below example requires you to have the helper functions added. Please refer to the helper functions section in the documentation. Below example requires you to have the helper functions added. Please refer to the helper functions section in the documentation.
```php ```php
@@ -1,20 +1,16 @@
<?php <?php
namespace Demo\Controllers; namespace Demo\Controllers;
use Pecee\SimpleRouter\SimpleRouter; class ApiController
{
class ApiController { public function index()
{
public function index() {
// The variable authenticated is set to true in the ApiVerification middleware class. // The variable authenticated is set to true in the ApiVerification middleware class.
header('content-type: application/json'); header('content-type: application/json');
echo json_encode([ echo json_encode([
'authenticated' => request()->authenticated 'authenticated' => request()->authenticated
]); ]);
} }
} }
@@ -1,28 +1,26 @@
<?php <?php
namespace Demo\Controllers; namespace Demo\Controllers;
class DefaultController { class DefaultController
{
public function index() { public function index()
{
// implement // implement
echo sprintf('DefaultController -> index (?fun=%s)', input()->get('fun')); echo sprintf('DefaultController -> index (?fun=%s)', input()->get('fun'));
} }
public function contact() { public function contact()
{
echo 'DefaultController -> contact'; echo 'DefaultController -> contact';
} }
public function companies($id = null) { public function companies($id = null)
{
echo 'DefaultController -> companies -> id: ' . $id; echo 'DefaultController -> companies -> id: ' . $id;
} }
public function notFound() { public function notFound()
{
echo 'Page not found'; echo 'Page not found';
} }
@@ -5,12 +5,12 @@ use Pecee\Handler\IExceptionHandler;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\RouterEntry;
class CustomExceptionHandler implements IExceptionHandler { class CustomExceptionHandler implements IExceptionHandler
{
public function handleError( Request $request, RouterEntry &$route = null, \Exception $error) { public function handleError(Request $request, RouterEntry &$route = null, \Exception $error)
{
// Return json errors if we encounter an error on /api. // Return json errors if we encounter an error on /api.
if(stripos($request->getUri(), '/api') !== false) { if (stripos($request->getUri(), '/api') !== false) {
header('content-type: application/json'); header('content-type: application/json');
echo json_encode([ echo json_encode([
'error' => $error->getMessage(), 'error' => $error->getMessage(),
@@ -20,7 +20,7 @@ class CustomExceptionHandler implements IExceptionHandler {
} }
// else we just throw the error // else we just throw the error
if($error->getCode() == 404) { if ($error->getCode() == 404) {
// Return 404 path // Return 404 path
$request->setUri('/404'); $request->setUri('/404');
@@ -5,15 +5,14 @@ use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\RouterEntry;
class ApiVerification implements IMiddleware { class ApiVerification implements IMiddleware
{
public function handle(Request $request, RouterEntry &$route) { public function handle(Request $request, RouterEntry &$route)
{
// Do authentication // Do authentication
$request->authenticated = true; $request->authenticated = true;
return $request; return $request;
} }
} }
@@ -3,8 +3,8 @@ namespace Demo\Middlewares;
use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Middleware\BaseCsrfVerifier;
class CsrfVerifier extends BaseCsrfVerifier { class CsrfVerifier extends BaseCsrfVerifier
{
/** /**
* CSRF validation will be ignored on the following urls. * CSRF validation will be ignored on the following urls.
*/ */
+5 -8
View File
@@ -1,29 +1,26 @@
<?php <?php
/** /**
* Custom router which handles default middlewares, default exceptions and things * Custom router which handles default middlewares, default exceptions and things
* that should be happen before and after the router is initialised. * that should be happen before and after the router is initialised.
*/ */
namespace Demo; namespace Demo;
use Pecee\SimpleRouter\SimpleRouter; use Pecee\SimpleRouter\SimpleRouter;
class Router extends SimpleRouter { class Router extends SimpleRouter
{
public static function start($defaultNamespace = null) { public static function start($defaultNamespace = null)
{
// Load our helpers // Load our helpers
require_once 'helpers.php'; require_once 'helpers.php';
// Load our custom routes // Load our custom routes
require_once 'routes.php'; require_once 'routes.php';
parent::setDefaultNamespace('\Demo\Controllers'); parent::setDefaultNamespace('\Demo');
// Do initial stuff // Do initial stuff
parent::start(); parent::start();
} }
} }
+10 -5
View File
@@ -1,7 +1,8 @@
<?php <?php
use Pecee\SimpleRouter\SimpleRouter; use Pecee\SimpleRouter\SimpleRouter;
function url($controller, $parameters = null, $getParams = null) { function url($controller, $parameters = null, $getParams = null)
{
SimpleRouter::getRoute($controller, $parameters, $getParams); SimpleRouter::getRoute($controller, $parameters, $getParams);
} }
@@ -9,7 +10,8 @@ function url($controller, $parameters = null, $getParams = null) {
* Get current csrf-token * Get current csrf-token
* @return null|string * @return null|string
*/ */
function csrf_token() { function csrf_token()
{
$token = new \Pecee\CsrfToken(); $token = new \Pecee\CsrfToken();
return $token->getToken(); return $token->getToken();
} }
@@ -18,7 +20,8 @@ function csrf_token() {
* Get request object * Get request object
* @return \Pecee\Http\Request * @return \Pecee\Http\Request
*/ */
function request() { function request()
{
return SimpleRouter::request(); return SimpleRouter::request();
} }
@@ -26,7 +29,8 @@ function request() {
* Get response object * Get response object
* @return \Pecee\Http\Response * @return \Pecee\Http\Response
*/ */
function response() { function response()
{
return SimpleRouter::response(); return SimpleRouter::response();
} }
@@ -34,6 +38,7 @@ function response() {
* Get input class * Get input class
* @return \Pecee\Http\Input\Input * @return \Pecee\Http\Input\Input
*/ */
function input() { function input()
{
return SimpleRouter::request()->getInput(); return SimpleRouter::request()->getInput();
} }
+2 -2
View File
@@ -7,7 +7,7 @@ use Demo\Router;
Router::csrfVerifier(new \Demo\Middlewares\CsrfVerifier()); Router::csrfVerifier(new \Demo\Middlewares\CsrfVerifier());
Router::group(['exceptionHandler' => 'Demo\Handlers\CustomExceptionHandler'], function() { Router::group(['exceptionHandler' => 'Demo\Handlers\CustomExceptionHandler'], function () {
Router::get('/', 'DefaultController@index')->setAlias('home'); Router::get('/', 'DefaultController@index')->setAlias('home');
Router::get('/contact', 'DefaultController@contact')->setAlias('contact'); Router::get('/contact', 'DefaultController@contact')->setAlias('contact');
@@ -16,7 +16,7 @@ Router::group(['exceptionHandler' => 'Demo\Handlers\CustomExceptionHandler'], fu
Router::basic('/companies/{id}', 'DefaultController@companies')->setAlias('companies'); Router::basic('/companies/{id}', 'DefaultController@companies')->setAlias('companies');
// Api // Api
Router::group(['prefix' => '/api', 'middleware' => 'Demo\Middlewares\ApiVerification'], function() { Router::group(['prefix' => '/api', 'middleware' => 'Demo\Middlewares\ApiVerification'], function () {
Router::resource('/demo', 'ApiController'); Router::resource('/demo', 'ApiController');
}); });
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace Pecee\Controller;
interface IRestController {
/**
* @return void
*/
function index();
/**
* @param mixed $id
* @return void
*/
function show($id);
/**
* @return void
*/
function store();
/**
* @return void
*/
function create();
/**
* View
* @param mixed $id
* @return void
*/
function edit($id);
/**
* @param mixed $id
* @return void
*/
function update($id);
/**
* @param mixed $id
* @return void
*/
function destroy($id);
}
+15 -9
View File
@@ -1,17 +1,19 @@
<?php <?php
namespace Pecee; namespace Pecee;
class CsrfToken { class CsrfToken
{
const CSRF_KEY = 'XSRF-TOKEN'; const CSRF_KEY = 'XSRF-TOKEN';
protected $token; protected $token;
/** /**
* Generate random identifier for CSRF token * Generate random identifier for CSRF token
*
* @return string * @return string
*/ */
public static function generateToken() { public static function generateToken()
{
if (function_exists('mcrypt_create_iv')) { if (function_exists('mcrypt_create_iv')) {
return bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); return bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
} }
@@ -24,8 +26,9 @@ class CsrfToken {
* @param string $token * @param string $token
* @return bool * @return bool
*/ */
public function validate($token) { public function validate($token)
if($token !== null && $this->getToken() !== null) { {
if ($token !== null && $this->getToken() !== null) {
return hash_equals($token, $this->getToken()); return hash_equals($token, $this->getToken());
} }
return false; return false;
@@ -36,7 +39,8 @@ class CsrfToken {
* *
* @param $token * @param $token
*/ */
public function setToken($token) { public function setToken($token)
{
setcookie(static::CSRF_KEY, $token, time() + 60 * 120, '/'); setcookie(static::CSRF_KEY, $token, time() + 60 * 120, '/');
} }
@@ -44,8 +48,9 @@ class CsrfToken {
* Get csrf token * Get csrf token
* @return string|null * @return string|null
*/ */
public function getToken(){ public function getToken()
if($this->hasToken()) { {
if ($this->hasToken()) {
return $_COOKIE[static::CSRF_KEY]; return $_COOKIE[static::CSRF_KEY];
} }
return null; return null;
@@ -55,7 +60,8 @@ class CsrfToken {
* Returns whether the csrf token has been defined * Returns whether the csrf token has been defined
* @return bool * @return bool
*/ */
public function hasToken() { public function hasToken()
{
return isset($_COOKIE[static::CSRF_KEY]); return isset($_COOKIE[static::CSRF_KEY]);
} }
+3 -1
View File
@@ -1,4 +1,6 @@
<?php <?php
namespace Pecee\Exception; namespace Pecee\Exception;
class RouterException extends \Exception { } class RouterException extends \Exception
{
}
@@ -1,4 +1,6 @@
<?php <?php
namespace Pecee\Exception; namespace Pecee\Exception;
class TokenMismatchException extends \Exception {} class TokenMismatchException extends \Exception
{
}
+2 -2
View File
@@ -4,8 +4,8 @@ namespace Pecee\Handler;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\RouterEntry;
interface IExceptionHandler { interface IExceptionHandler
{
/** /**
* @param Request $request * @param Request $request
* @param RouterEntry|null $route * @param RouterEntry|null $route
+52 -54
View File
@@ -3,8 +3,8 @@ namespace Pecee\Http\Input;
use Pecee\Http\Request; use Pecee\Http\Request;
class Input { class Input
{
/** /**
* @var \Pecee\Http\Input\InputCollection * @var \Pecee\Http\Input\InputCollection
*/ */
@@ -25,7 +25,8 @@ class Input {
*/ */
protected $request; protected $request;
public function __construct(Request $request) { public function __construct(Request $request)
{
$this->request = $request; $this->request = $request;
$this->setGet(); $this->setGet();
$this->setPost(); $this->setPost();
@@ -37,17 +38,17 @@ class Input {
* @param array|null $filter Only take items in filter * @param array|null $filter Only take items in filter
* @return array * @return array
*/ */
public function all(array $filter = null) { public function all(array $filter = null)
{
$output = $_POST; $output = $_POST;
if($this->request->getMethod() === 'post') { if ($this->request->getMethod() === 'post') {
$contents = file_get_contents('php://input'); $contents = file_get_contents('php://input');
if (stripos(trim($contents), '{') === 0) { if (stripos(trim($contents), '{') === 0) {
$output = json_decode($contents, true); $output = json_decode($contents, true);
if($output === false) { if ($output === false) {
$output = array(); $output = array();
} }
} }
@@ -55,7 +56,7 @@ class Input {
$output = array_merge($_GET, $output); $output = array_merge($_GET, $output);
if($filter !== null) { if ($filter !== null) {
$output = array_filter($output, function ($key) use ($filter) { $output = array_filter($output, function ($key) use ($filter) {
if (in_array($key, $filter)) { if (in_array($key, $filter)) {
return true; return true;
@@ -68,20 +69,20 @@ class Input {
return $output; return $output;
} }
public function getObject($index, $default = null) { public function getObject($index, $default = null)
$key = (strpos($index, '[') > -1) ? substr($index, strpos($index, '[')+1, strpos($index, ']') - strlen($index)) : null; {
$key = (strpos($index, '[') > -1) ? substr($index, strpos($index, '[') + 1, strpos($index, ']') - strlen($index)) : null;
$index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index; $index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index;
$element = $this->get->findFirst($index); $element = $this->get->findFirst($index);
if($element !== null) { if ($element !== null) {
return ($key !== null) ? $element[$key] : $element; return ($key !== null) ? $element[$key] : $element;
} }
if($this->request->getMethod() !== 'get') { if ($this->request->getMethod() !== 'get') {
$element = $this->post->findFirst($index); $element = $this->post->findFirst($index);
if ($element !== null) { if ($element !== null) {
return ($key !== null) ? $element[$key] : $element; return ($key !== null) ? $element[$key] : $element;
} }
@@ -101,13 +102,13 @@ class Input {
* @param string|null $default * @param string|null $default
* @return string|null * @return string|null
*/ */
public function get($index, $default = null) { public function get($index, $default = null)
{
$item = $this->getObject($index); $item = $this->getObject($index);
if($item !== null) { if ($item !== null) {
if($item instanceof InputCollection || $item instanceof InputFile) { if ($item instanceof InputCollection || $item instanceof InputFile) {
return $item; return $item;
} }
@@ -117,23 +118,25 @@ class Input {
return $default; return $default;
} }
public function exists($index) { public function exists($index)
{
return ($this->getObject($index) !== null); return ($this->getObject($index) !== null);
} }
public function setGet() { public function setGet()
{
$this->get = new InputCollection(); $this->get = new InputCollection();
if(count($_GET)) { if (count($_GET) > 0) {
foreach($_GET as $key => $get) { foreach ($_GET as $key => $get) {
if(!is_array($get)) { if (is_array($get) === false) {
$this->get->{$key} = new InputItem($key, $get); $this->get->{$key} = new InputItem($key, $get);
continue; continue;
} }
$output = new InputCollection(); $output = new InputCollection();
foreach($get as $k => $g) { foreach ($get as $k => $g) {
$output->{$k} = new InputItem($k, $g); $output->{$k} = new InputItem($k, $g);
} }
@@ -142,26 +145,27 @@ class Input {
} }
} }
public function setPost() { public function setPost()
{
$this->post = new InputCollection(); $this->post = new InputCollection();
$postVars = $_POST; $postVars = $_POST;
if(in_array($this->request->getMethod(), ['put', 'patch', 'delete'])) { if (in_array($this->request->getMethod(), ['put', 'patch', 'delete']) === true) {
parse_str(file_get_contents('php://input'), $postVars); parse_str(file_get_contents('php://input'), $postVars);
} }
if(count($postVars)) { if (count($postVars) > 0) {
foreach($postVars as $key => $post) { foreach ($postVars as $key => $post) {
if(!is_array($post)) { if (is_array($post) === false) {
$this->post->{strtolower($key)} = new InputItem($key, $post); $this->post->{strtolower($key)} = new InputItem($key, $post);
continue; continue;
} }
$output = new InputCollection(); $output = new InputCollection();
foreach($post as $k => $p) { foreach ($post as $k => $p) {
$output->{$k} = new InputItem($k, $p); $output->{$k} = new InputItem($k, $p);
} }
@@ -170,38 +174,32 @@ class Input {
} }
} }
public function setFile() { public function setFile()
{
$this->file = new InputCollection(); $this->file = new InputCollection();
if(count($_FILES)) { if (count($_FILES) > 0) {
foreach($_FILES as $key => $value) { foreach ($_FILES as $key => $values) {
// Multiple files
if(!is_array($value['name'])) { // Handle array input
// Strip empty values if (is_array($values['name']) === false && trim($values['error']) !== '4') {
if($value['error'] != '4') { $values['index'] = $key;
$file = new InputFile($key); $this->file->{strtolower($key)} = InputFile::createFromArray($values);
$file->setName($value['name']);
$file->setSize($value['size']);
$file->setType($value['type']);
$file->setTmpName($value['tmp_name']);
$file->setError($value['error']);
$this->file->{strtolower($key)} = $file;
}
continue; continue;
} }
$output = new InputCollection(); $output = new InputCollection();
foreach($value['name'] as $k=>$val) { foreach ($values['name'] as $k => $val) {
// Strip empty values if (trim($val['error'][$k]) !== '4') {
if($value['error'][$k] != '4') { $output->{$k} = InputFile::createFromArray([
$file = new InputFile($k); 'index' => $k,
$file->setName($value['name'][$k]); 'error' => $val['error'][$k],
$file->setSize($value['size'][$k]); 'tmp_name' => $val['tmp_name'][$k],
$file->setType($value['type'][$k]); 'type' => $val['type'][$k],
$file->setTmpName($value['tmp_name'][$k]); 'size' => $val['size'][$k],
$file->setError($value['error'][$k]); 'name' => $val['name'][$k]
$output->{$k} = $file; ]);
} }
} }
+44 -35
View File
@@ -1,61 +1,67 @@
<?php <?php
namespace Pecee\Http\Input; namespace Pecee\Http\Input;
class InputCollection implements \IteratorAggregate { class InputCollection implements \IteratorAggregate
{
protected $data = array(); protected $data = array();
/** /**
* Search for input element matching index. * Search for input element matching index.
* Useful for searching for finding items where $index doesn't contain form name.
* *
* @param string $index * @param string $index
* @param string|null $defaultValue * @param string|null $default
* @return mixed * @return InputItem
*/ */
public function findFirst($index, $defaultValue = null) { public function findFirst($index, $default = null)
if(count($this->data)) { {
if (count($this->data) > 0) {
if(isset($this->data[$index])) { if (isset($this->data[$index])) {
return $this->data[$index]; return $this->data[$index];
} }
foreach($this->data as $key => $value) { foreach ($this->data as $key => $input) {
if(strtolower($index) === strtolower($key)) { if (strtolower($index) === strtolower($key)) {
return $value; return $input;
} }
} }
} }
return $defaultValue; return $default;
}
public function getValue($index, $defaultValue = null) {
if(count($this->data)) {
if(isset($this->data[$index])) {
return $this->data[$index]->getValue();
}
foreach($this->data as $key => $value) {
if(strtolower($index) === strtolower($key)) {
return $value->getValue();
}
}
}
return $defaultValue;
} }
/** /**
* @param $index * Get input element value matching index
*
* @param string $index
* @param string|null $default
* @return string|null
*/
public function get($index, $default = null)
{
$input = $this->findFirst($index);
if($input !== null) {
if(trim($input->getValue()) === '') {
return $default;
}
return $input;
}
return $default;
}
/**
* @param string $index
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* @return InputItem * @return InputItem
*/ */
public function __get($index) { public function __get($index)
{
$item = $this->findFirst($index); $item = $this->findFirst($index);
// Ensure that item are always available // Ensure that item are always available
if($item === null) { if ($item === null) {
$this->data[$index] = new InputItem($index, null); $this->data[$index] = new InputItem($index, null);
return $this->data[$index]; return $this->data[$index];
} }
@@ -63,11 +69,13 @@ class InputCollection implements \IteratorAggregate {
return $item; return $item;
} }
public function __set($index, $value) { public function __set($index, $value)
{
$this->data[$index] = $value; $this->data[$index] = $value;
} }
public function getData() { public function getData()
{
return $this->data; return $this->data;
} }
@@ -78,7 +86,8 @@ class InputCollection implements \IteratorAggregate {
* <b>Traversable</b> * <b>Traversable</b>
* @since 5.0.0 * @since 5.0.0
*/ */
public function getIterator() { public function getIterator()
{
return new \ArrayIterator($this->data); return new \ArrayIterator($this->data);
} }
+59 -18
View File
@@ -1,68 +1,109 @@
<?php <?php
namespace Pecee\Http\Input; namespace Pecee\Http\Input;
class InputFile extends InputItem { class InputFile extends InputItem
{
protected $name; public $size;
protected $size; public $type;
protected $type; public $error;
protected $error; public $tmpName;
protected $tmpName;
/** /**
* @return string * @return string
*/ */
public function getSize() { public function getSize()
{
return $this->size; return $this->size;
} }
/** /**
* @return string * @return string
*/ */
public function getType() { public function getType()
{
return $this->type; return $this->type;
} }
/** /**
* @return string * @return string
*/ */
public function getError() { public function getError()
{
return $this->error; return $this->error;
} }
public function getMime()
{
return $this->getType();
}
/** /**
* @return string * @return string
*/ */
public function getTmpName() { public function getTmpName()
{
return $this->tmpName; return $this->tmpName;
} }
public function getExtension() { public function getExtension()
{
return pathinfo($this->getName(), PATHINFO_EXTENSION); return pathinfo($this->getName(), PATHINFO_EXTENSION);
} }
public function move($destination) { public function move($destination)
{
return move_uploaded_file($this->tmpName, $destination); return move_uploaded_file($this->tmpName, $destination);
} }
public function getContents() { public function getContents()
{
return file_get_contents($this->tmpName); return file_get_contents($this->tmpName);
} }
public function setTmpName($name) { public function setTmpName($name)
{
$this->tmpName = $name; $this->tmpName = $name;
} }
public function setSize($size) { public function setSize($size)
{
$this->size = $size; $this->size = $size;
} }
public function setType($type) { public function setType($type)
{
$this->type = $type; $this->type = $type;
} }
public function setError($error) { public function setError($error)
{
$this->error = $error; $this->error = $error;
} }
/**
* Create from array
* @param array $values
* @return static
*/
public static function createFromArray(array $values)
{
if(!isset($values['index'])) {
throw new \InvalidArgumentException('Index key is required');
}
$input = new static($values['index']);
$input->setTmpName((isset($values['error']) ? $values['error'] : null));
$input->setName((isset($values['name']) ? $values['name'] : null));
$input->setSize((isset($values['size']) ? $values['size'] : null));
$input->setType((isset($values['type']) ? $values['type'] : null));
$input->setError((isset($values['tmp_name']) ? $values['tmp_name'] : null));
return $input;
}
public function __toString()
{
return (string)$this->tmpName;
}
} }
+20 -13
View File
@@ -1,13 +1,14 @@
<?php <?php
namespace Pecee\Http\Input; namespace Pecee\Http\Input;
class InputItem { class InputItem
{
public $index;
public $name;
public $value;
protected $index; public function __construct($index, $value = null)
protected $name; {
protected $value;
public function __construct($index, $value = null) {
$this->index = $index; $this->index = $index;
$this->value = $value; $this->value = $value;
@@ -18,21 +19,24 @@ class InputItem {
/** /**
* @return array * @return array
*/ */
public function getName() { public function getName()
{
return $this->name; return $this->name;
} }
/** /**
* @return array * @return array
*/ */
public function getValue() { public function getValue()
{
return $this->value; return $this->value;
} }
/** /**
* @return string * @return string
*/ */
public function getIndex() { public function getIndex()
{
return $this->index; return $this->index;
} }
@@ -41,7 +45,8 @@ class InputItem {
* @param string $name * @param string $name
* @return static $this * @return static $this
*/ */
public function setName($name) { public function setName($name)
{
$this->name = $name; $this->name = $name;
return $this; return $this;
} }
@@ -51,13 +56,15 @@ class InputItem {
* @param string $value * @param string $value
* @return static $this * @return static $this
*/ */
public function setValue($value) { public function setValue($value)
{
$this->value = $value; $this->value = $value;
return $this; return $this;
} }
public function __toString() { public function __toString()
return (string)$this->getValue(); {
return (string)$this->value;
} }
} }
+22 -17
View File
@@ -6,8 +6,8 @@ use Pecee\Exception\TokenMismatchException;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\RouterEntry;
class BaseCsrfVerifier implements IMiddleware { class BaseCsrfVerifier implements IMiddleware
{
const POST_KEY = 'csrf-token'; const POST_KEY = 'csrf-token';
const HEADER_KEY = 'X-CSRF-TOKEN'; const HEADER_KEY = 'X-CSRF-TOKEN';
@@ -15,7 +15,8 @@ class BaseCsrfVerifier implements IMiddleware {
protected $csrfToken; protected $csrfToken;
protected $token; protected $token;
public function __construct() { public function __construct()
{
$this->csrfToken = new CsrfToken(); $this->csrfToken = new CsrfToken();
// Generate or get the CSRF-Token from Cookie. // Generate or get the CSRF-Token from Cookie.
@@ -27,22 +28,22 @@ class BaseCsrfVerifier implements IMiddleware {
* @param Request $request * @param Request $request
* @return bool * @return bool
*/ */
protected function skip(Request $request) { protected function skip(Request $request)
{
if($this->except === null || !is_array($this->except)) { if ($this->except === null || is_array($this->except) === false) {
return false; return false;
} }
foreach($this->except as $url) { foreach ($this->except as $url) {
$url = rtrim($url, '/'); $url = rtrim($url, '/');
if($url[strlen($url)-1] === '*') { if ($url[strlen($url) - 1] === '*') {
$url = rtrim($url, '*'); $url = rtrim($url, '*');
$skip = (stripos($request->getUri(), $url) === 0); $skip = (stripos($request->getUri(), $url) === 0);
} else { } else {
$skip = ($url === rtrim($request->getUri(), '/')); $skip = ($url === rtrim($request->getUri(), '/'));
} }
if($skip) { if ($skip) {
return true; return true;
} }
} }
@@ -50,18 +51,19 @@ class BaseCsrfVerifier implements IMiddleware {
return false; return false;
} }
public function handle(Request $request, RouterEntry &$route = null) { public function handle(Request $request, RouterEntry &$route = null)
{
if($request->getMethod() !== 'get' && !$this->skip($request)) { if ($request->getMethod() !== 'get' && !$this->skip($request)) {
$token = $request->getInput()->post->getValue(static::POST_KEY); $token = $request->getInput()->post->getValue(static::POST_KEY);
// If the token is not posted, check headers for valid x-csrf-token // If the token is not posted, check headers for valid x-csrf-token
if($token === null) { if ($token === null) {
$token = $request->getHeader(static::HEADER_KEY); $token = $request->getHeader(static::HEADER_KEY);
} }
if( !$this->csrfToken->validate($token) ) { if (!$this->csrfToken->validate($token)) {
throw new TokenMismatchException('Invalid csrf-token.'); throw new TokenMismatchException('Invalid csrf-token.');
} }
@@ -69,21 +71,24 @@ class BaseCsrfVerifier implements IMiddleware {
} }
public function generateToken() { public function generateToken()
{
$token = $this->csrfToken->generateToken(); $token = $this->csrfToken->generateToken();
$this->csrfToken->setToken($token); $this->csrfToken->setToken($token);
return $token; return $token;
} }
public function hasToken() { public function hasToken()
if($this->token != null) { {
if ($this->token != null) {
return true; return true;
} }
return $this->csrfToken->hasToken(); return $this->csrfToken->hasToken();
} }
public function getToken() { public function getToken()
{
return $this->token; return $this->token;
} }
+2 -2
View File
@@ -4,8 +4,8 @@ namespace Pecee\Http\Middleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\RouterEntry;
interface IMiddleware { interface IMiddleware
{
/** /**
* @param Request $request * @param Request $request
* @param RouterEntry $route * @param RouterEntry $route
+65 -44
View File
@@ -3,8 +3,8 @@ namespace Pecee\Http;
use Pecee\Http\Input\Input; use Pecee\Http\Input\Input;
class Request { class Request
{
protected $data = array(); protected $data = array();
protected $headers; protected $headers;
protected $host; protected $host;
@@ -12,54 +12,56 @@ class Request {
protected $method; protected $method;
protected $input; protected $input;
public function __construct()
public function __construct() { {
$this->parseHeaders(); $this->parseHeaders();
$this->input = new Input($this); $this->input = new Input($this);
$this->host = $this->getHeader('http_host');; $this->host = $this->getHeader('http-host');;
$this->uri = $this->getHeader('request_uri'); $this->uri = $this->getHeader('request-uri');
$this->method = strtolower($this->input->post->findFirst('_method', $this->getHeader('request_method'))); $this->method = strtolower($this->input->post->findFirst('_method', $this->getHeader('request-method')));
} }
protected function parseHeaders() { protected function parseHeaders()
{
$this->headers = array(); $this->headers = array();
foreach ($_SERVER as $name => $value) { foreach ($_SERVER as $name => $value) {
$this->headers[strtolower($name)] = $value; $this->headers[strtolower($name)] = $value;
$this->headers[strtolower(str_replace('_', '-', $name))] = $value;
} }
} }
public function isSecure() { public function isSecure()
if($this->getHeader('http_x_forwarded_proto') === 'https') { {
if ($this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443) {
return true; return true;
} }
if($this->getHeader('https') !== null) { return false;
return true;
}
return ($this->getHeader('server_port') === 443);
} }
/** /**
* @return string * @return string
*/ */
public function getUri() { public function getUri()
{
return $this->uri; return $this->uri;
} }
/** /**
* @return string * @return string
*/ */
public function getHost() { public function getHost()
{
return $this->host; return $this->host;
} }
/** /**
* @return string * @return string
*/ */
public function getMethod() { public function getMethod()
{
return $this->method; return $this->method;
} }
@@ -67,23 +69,26 @@ class Request {
* Get http basic auth user * Get http basic auth user
* @return string|null * @return string|null
*/ */
public function getUser() { public function getUser()
return $this->getHeader('php_auth_user'); {
return $this->getHeader('php-auth-user');
} }
/** /**
* Get http basic auth password * Get http basic auth password
* @return string|null * @return string|null
*/ */
public function getPassword() { public function getPassword()
return $this->getHeader('php_auth_pw'); {
return $this->getHeader('php-auth-pw');
} }
/** /**
* Get all headers * Get all headers
* @return array * @return array
*/ */
public function getHeaders() { public function getHeaders()
{
return $this->headers; return $this->headers;
} }
@@ -91,41 +96,47 @@ class Request {
* Get id address * Get id address
* @return string * @return string
*/ */
public function getIp() { public function getIp()
if($this->getHeader('http_cf_connecting_ip') !== null) { {
return $this->getHeader('http_cf_connecting_ip'); if ($this->getHeader('http-cf-connecting-ip') !== null) {
return $this->getHeader('http-cf-connecting-ip');
} }
if($this->getHeader('http_x_forwarded_for') !== null && strlen($this->getHeader('http_x_forwarded_for'))) { if ($this->getHeader('http-x-forwarded-for') !== null && strlen($this->getHeader('http-x-forwarded-for'))) {
return $this->getHeader('http_x_forwarded_for'); return $this->getHeader('http-x-forwarded_for');
} }
return $this->getHeader('remote_addr'); return $this->getHeader('remote-addr');
} }
/** /**
* Get referer * Get referer
* @return string * @return string
*/ */
public function getReferer() { public function getReferer()
return $this->getHeader('http_referer'); {
return $this->getHeader('http-referer');
} }
/** /**
* Get user agent * Get user agent
* @return string * @return string
*/ */
public function getUserAgent() { public function getUserAgent()
return $this->getHeader('http_user_agent'); {
return $this->getHeader('http-user-agent');
} }
/** /**
* Get header value by name * Get header value by name
*
* @param string $name * @param string $name
* @param object|null $defaultValue * @param object|null $defaultValue
*
* @return string|null * @return string|null
*/ */
public function getHeader($name, $defaultValue = null) { public function getHeader($name, $defaultValue = null)
{
return isset($this->headers[strtolower($name)]) ? $this->headers[strtolower($name)] : $defaultValue; return isset($this->headers[strtolower($name)]) ? $this->headers[strtolower($name)] : $defaultValue;
} }
@@ -133,53 +144,63 @@ class Request {
* Get input class * Get input class
* @return Input * @return Input
*/ */
public function getInput() { public function getInput()
{
return $this->input; return $this->input;
} }
/** /**
* Is format accepted * Is format accepted
*
* @param string $format * @param string $format
*
* @return bool * @return bool
*/ */
public function isFormatAccepted($format) { public function isFormatAccepted($format)
return ($this->getHeader('http_accept') !== null && stripos($this->getHeader('http_accept'), $format) > -1); {
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) > -1);
} }
/** /**
* Get accept formats * Get accept formats
* @return array * @return array
*/ */
public function getAcceptFormats() { public function getAcceptFormats()
return explode(',', $this->getHeader('http_accept')); {
return explode(',', $this->getHeader('http-accept'));
} }
/** /**
* @param string $uri * @param string $uri
*/ */
public function setUri($uri) { public function setUri($uri)
{
$this->uri = $uri; $this->uri = $uri;
} }
/** /**
* @param string $host * @param string $host
*/ */
public function setHost($host) { public function setHost($host)
{
$this->host = $host; $this->host = $host;
} }
/** /**
* @param string $method * @param string $method
*/ */
public function setMethod($method) { public function setMethod($method)
{
$this->method = $method; $this->method = $method;
} }
public function __set($name, $value = null) { public function __set($name, $value = null)
{
$this->data[$name] = $value; $this->data[$name] = $value;
} }
public function __get($name) { public function __get($name)
{
return isset($this->data[$name]) ? $this->data[$name] : null; return isset($this->data[$name]) ? $this->data[$name] : null;
} }
+25 -16
View File
@@ -1,12 +1,12 @@
<?php <?php
namespace Pecee\Http; namespace Pecee\Http;
class Response { class Response
{
protected $request; protected $request;
public function __construct(Request $request) { public function __construct(Request $request)
{
$this->request = $request; $this->request = $request;
} }
@@ -16,7 +16,8 @@ class Response {
* @param int $code * @param int $code
* @return static * @return static
*/ */
public function httpCode($code) { public function httpCode($code)
{
http_response_code($code); http_response_code($code);
return $this; return $this;
} }
@@ -27,8 +28,9 @@ class Response {
* @param string $url * @param string $url
* @param int $httpCode * @param int $httpCode
*/ */
public function redirect($url, $httpCode = null) { public function redirect($url, $httpCode = null)
if($httpCode !== null) { {
if ($httpCode !== null) {
$this->httpCode($httpCode); $this->httpCode($httpCode);
} }
@@ -36,7 +38,8 @@ class Response {
die(); die();
} }
public function refresh() { public function refresh()
{
$this->redirect($this->request->getUri()); $this->redirect($this->request->getUri());
} }
@@ -45,7 +48,8 @@ class Response {
* @param string $name * @param string $name
* @return static * @return static
*/ */
public function auth($name = '') { public function auth($name = '')
{
$this->headers([ $this->headers([
'WWW-Authenticate: Basic realm="' . $name . '"', 'WWW-Authenticate: Basic realm="' . $name . '"',
'HTTP/1.0 401 Unauthorized' 'HTTP/1.0 401 Unauthorized'
@@ -53,7 +57,8 @@ class Response {
return $this; return $this;
} }
public function cache($eTag, $lastModified = 2592000) { public function cache($eTag, $lastModified = 2592000)
{
$this->headers([ $this->headers([
'Cache-Control: public', 'Cache-Control: public',
@@ -61,8 +66,9 @@ class Response {
'Etag: ' . $eTag 'Etag: ' . $eTag
]); ]);
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $lastModified || if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $lastModified ||
isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $eTag) { isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $eTag
) {
$this->headers([ $this->headers([
'HTTP/1.1 304 Not Modified' 'HTTP/1.1 304 Not Modified'
@@ -78,7 +84,8 @@ class Response {
* Json encode array * Json encode array
* @param array $value * @param array $value
*/ */
public function json(array $value) { public function json(array $value)
{
$this->header('Content-type: application/json'); $this->header('Content-type: application/json');
echo json_encode($value); echo json_encode($value);
die(); die();
@@ -89,7 +96,8 @@ class Response {
* @param string $value * @param string $value
* @return static * @return static
*/ */
public function header($value) { public function header($value)
{
header($value); header($value);
return $this; return $this;
} }
@@ -99,8 +107,9 @@ class Response {
* @param array $headers * @param array $headers
* @return static * @return static
*/ */
public function headers(array $headers) { public function headers(array $headers)
foreach($headers as $header) { {
foreach ($headers as $header) {
header($header); header($header);
} }
return $this; return $this;
+7 -5
View File
@@ -1,11 +1,13 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
interface IControllerRoute { interface IControllerRoute
{
public function getController(); public function getController();
public function setController($controller);
public function getMethod();
public function setMethod($method);
public function setController($controller);
public function getMethod();
public function setMethod($method);
} }
+3 -3
View File
@@ -1,9 +1,9 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
interface ILoadableRoute { interface ILoadableRoute
{
public function getUrl(); public function getUrl();
public function setUrl($url);
public function setUrl($url);
} }
+19 -13
View File
@@ -1,14 +1,15 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
abstract class LoadableRoute extends RouterEntry implements ILoadableRoute { abstract class LoadableRoute extends RouterEntry implements ILoadableRoute
{
const PARAMETERS_REGEX_MATCH = '{([A-Za-z\-\_]*?)\?{0,1}}'; const PARAMETERS_REGEX_MATCH = '{([A-Za-z\-\_]*?)\?{0,1}}';
protected $url; protected $url;
protected $alias; protected $alias;
public function getUrl() { public function getUrl()
{
return $this->url; return $this->url;
} }
@@ -18,11 +19,12 @@ abstract class LoadableRoute extends RouterEntry implements ILoadableRoute {
* @param string $url * @param string $url
* @return static * @return static
*/ */
public function setUrl($url) { public function setUrl($url)
$this->url = '/' . trim($url, '/') . '/'; {
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
if(preg_match_all('/' . static::PARAMETERS_REGEX_MATCH . '/is', $this->url, $matches)) { if (preg_match_all('/' . static::PARAMETERS_REGEX_MATCH . '/is', $this->url, $matches)) {
if (count($matches[1])) { if (count($matches[1]) > 0) {
foreach ($matches[1] as $key) { foreach ($matches[1] as $key) {
$this->parameters[$key] = null; $this->parameters[$key] = null;
} }
@@ -36,7 +38,8 @@ abstract class LoadableRoute extends RouterEntry implements ILoadableRoute {
* Get alias for the url which can be used when getting the url route. * Get alias for the url which can be used when getting the url route.
* @return string|array * @return string|array
*/ */
public function getAlias(){ public function getAlias()
{
return $this->alias; return $this->alias;
} }
@@ -46,9 +49,10 @@ abstract class LoadableRoute extends RouterEntry implements ILoadableRoute {
* @param string $name * @param string $name
* @return bool * @return bool
*/ */
public function hasAlias($name) { public function hasAlias($name)
{
if ($this->getAlias() !== null) { if ($this->getAlias() !== null) {
if (is_array($this->getAlias())) { if (is_array($this->getAlias()) === true) {
foreach ($this->getAlias() as $alias) { foreach ($this->getAlias() as $alias) {
if (strtolower($alias) === strtolower($name)) { if (strtolower($alias) === strtolower($name)) {
return true; return true;
@@ -66,15 +70,17 @@ abstract class LoadableRoute extends RouterEntry implements ILoadableRoute {
* @param string|array $alias * @param string|array $alias
* @return static * @return static
*/ */
public function setAlias($alias){ public function setAlias($alias)
{
$this->alias = $alias; $this->alias = $alias;
return $this; return $this;
} }
public function setData(array $settings) { public function setData(array $settings)
{
// Change as to alias // Change as to alias
if(isset($settings['as'])) { if (isset($settings['as'])) {
$this->setAlias($settings['as']); $this->setAlias($settings['as']);
} }
+181 -178
View File
@@ -7,10 +7,14 @@ use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\Http\Response; use Pecee\Http\Response;
class RouterBase { class RouterBase
{
protected static $instance; protected static $instance;
protected $parameterModifiers = '{}';
protected $parameterOptionalSymbol = '?';
/** /**
* Current request * Current request
* @var Request * @var Request
@@ -48,12 +52,6 @@ class RouterBase {
*/ */
protected $backStack; protected $backStack;
/**
* The default namespace that all routes will inherit
* @var string
*/
protected $defaultNamespace;
/** /**
* List of added bootmanagers * List of added bootmanagers
* @var array * @var array
@@ -82,27 +80,34 @@ class RouterBase {
* List over route changes (to avoid endless-looping) * List over route changes (to avoid endless-looping)
* @var array * @var array
*/ */
protected $routeRewrites = array(); protected $routeRewrites = [];
/**
* If the route has been rewritten/changed this property will contain the original url.
* @var string
*/
protected $originalUrl; protected $originalUrl;
/** /**
* Get current router instance * Get current router instance
* @return static * @return static
*/ */
public static function getInstance() { public static function getInstance()
if(static::$instance === null) { {
if (static::$instance === null) {
static::$instance = new static(); static::$instance = new static();
} }
return static::$instance; return static::$instance;
} }
public function __construct() { public function __construct()
{
$this->reset(); $this->reset();
} }
public function reset() { public function reset()
{
$this->processingRoute = false; $this->processingRoute = false;
$this->request = new Request(); $this->request = new Request();
$this->response = new Response($this->request); $this->response = new Response($this->request);
@@ -118,8 +123,9 @@ class RouterBase {
* @param RouterEntry $route * @param RouterEntry $route
* @return RouterEntry * @return RouterEntry
*/ */
public function addRoute(RouterEntry $route) { public function addRoute(RouterEntry $route)
if($this->processingRoute) { {
if ($this->processingRoute) {
$this->backStack[] = $route; $this->backStack[] = $route;
} else { } else {
$this->routes[] = $route; $this->routes[] = $route;
@@ -129,96 +135,89 @@ class RouterBase {
} }
protected function processRoutes(array $routes, array $settings = array(), array $prefixes = array(), RouterEntry $parent = null) { protected function processRoutes(array $routes, array $settings = array(), array $prefixes = array(), RouterEntry $parent = null) {
$mergedSettings = [];
// Loop through each route-request // Loop through each route-request
/* @var $route RouterEntry */ /* @var $route RouterEntry */
for($i = 0; $i < count($routes); $i++) { foreach ($routes as $route) {
$route = $routes[$i];
$route->setData($settings); $route->setData($settings);
if($parent !== null) { if ($parent !== null) {
if($parent instanceof RouterGroup) {
if ($parent->getPrefix() !== null && trim($parent->getPrefix(), '/') !== '') {
$prefixes[] = trim($parent->getPrefix(), '/');
}
}
$route->setParent($parent); $route->setParent($parent);
} }
if($route->getNamespace() === null && $this->defaultNamespace !== null) { if ($route instanceof ILoadableRoute) {
$namespace = $this->defaultNamespace;
if ($route->getNamespace()) { if($parent !== null && count($prefixes)) {
$namespace .= '\\' . $route->getNamespace(); $route->setUrl(trim(join('/', $prefixes) . $route->getUrl(), '/'));
} }
$route->setNamespace($namespace);
}
if($route instanceof ILoadableRoute) {
$route->setUrl( trim(join('/', $prefixes) . $route->getUrl(), '/') );
$this->controllerUrlMap[] = $route; $this->controllerUrlMap[] = $route;
} elseif($route instanceof RouterGroup) {
} elseif ($route instanceof RouterGroup) {
if ($route->getPrefix() !== null && trim($route->getPrefix(), '/') !== '') {
$prefixes[] = trim($route->getPrefix(), '/');
}
if ($route->getCallback() !== null && is_callable($route->getCallback())) { if ($route->getCallback() !== null && is_callable($route->getCallback())) {
$this->processingRoute = true; $this->processingRoute = true;
$route->renderRoute($this->request); $route->renderRoute($this->request);
$this->processingRoute = false; $this->processingRoute = false;
if ($route->matchRoute($this->request)) { if ($route->matchRoute($this->request)) {
$settings = array_merge($settings, $route->getMergeableData()); $mergedSettings = array_merge($mergedSettings, $route->getMergeableData());
// Add ExceptionHandler // Add ExceptionHandler
if (count($route->getExceptionHandlers())) { if (count($route->getExceptionHandlers()) > 0) {
$this->exceptionHandlers = array_merge($route->getExceptionHandlers(), $this->exceptionHandlers); $this->exceptionHandlers = array_merge($route->getExceptionHandlers(),
$this->exceptionHandlers);
}
}
} }
} }
} if (count($this->backStack) > 0) {
}
if(count($this->backStack)) {
$backStack = $this->backStack; $backStack = $this->backStack;
$this->backStack = array(); $this->backStack = array();
// Route any routes added to the backstack // Route any routes added to the backstack
$this->processRoutes($backStack, $settings, $prefixes, $route); $this->processRoutes($backStack, $mergedSettings, $prefixes, $route);
} }
$prefixes = [];
} }
} }
public function routeRequest($rewrite = false) { public function routeRequest($rewrite = false)
{
$this->loadedRoute = null; $this->loadedRoute = null;
$routeNotAllowed = false; $routeNotAllowed = false;
try { try {
// Initialize boot-managers // Initialize boot-managers
if(count($this->bootManagers)) { if (count($this->bootManagers) > 0) {
/* @var $manager RouterBootManager */ /* @var $manager RouterBootManager */
foreach($this->bootManagers as $manager) { foreach ($this->bootManagers as $manager) {
$this->request = $manager->boot($this->request); $this->request = $manager->boot($this->request);
if(!($this->request instanceof Request)) { if (!($this->request instanceof Request)) {
throw new RouterException('Custom router bootmanager "'. get_class($manager) .'" must return instance of Request.'); throw new RouterException('Custom router bootmanager "' . get_class($manager) . '" must return instance of Request.');
} }
} }
} }
if($rewrite === false) { if ($rewrite === false) {
// Loop through each route-request // Loop through each route-request
$this->processRoutes($this->routes); $this->processRoutes($this->routes);
if($this->csrfVerifier !== null) { if ($this->csrfVerifier !== null) {
// Verify csrf token for request // Verify csrf token for request
$this->csrfVerifier->handle($this->request); $this->csrfVerifier->handle($this->request);
@@ -228,13 +227,11 @@ class RouterBase {
} }
/* @var $route RouterEntry */ /* @var $route RouterEntry */
for ($i = 0; $i < count($this->controllerUrlMap); $i++) { foreach ($this->controllerUrlMap as $route) {
$route = $this->controllerUrlMap[$i];
if ($route->matchRoute($this->request)) { if ($route->matchRoute($this->request)) {
if (count($route->getRequestMethods()) && !in_array($this->request->getMethod(), $route->getRequestMethods())) { if (count($route->getRequestMethods()) > 0 && !in_array($this->request->getMethod(), $route->getRequestMethods())) {
$routeNotAllowed = true; $routeNotAllowed = true;
continue; continue;
} }
@@ -242,7 +239,7 @@ class RouterBase {
$this->loadedRoute = $route; $this->loadedRoute = $route;
$this->loadedRoute->loadMiddleware($this->request, $this->loadedRoute); $this->loadedRoute->loadMiddleware($this->request, $this->loadedRoute);
if($this->request->getUri() !== $this->originalUrl && !in_array($this->request->getUri(), $this->routeRewrites)) { if ($this->request->getUri() !== $this->originalUrl && !in_array($this->request->getUri(), $this->routeRewrites)) {
$this->routeRewrites[] = $this->request->getUri(); $this->routeRewrites[] = $this->request->getUri();
$this->routeRequest(true); $this->routeRequest(true);
return; return;
@@ -256,23 +253,24 @@ class RouterBase {
} }
} }
} catch(\Exception $e) { } catch (\Exception $e) {
$this->handleException($e); $this->handleException($e);
} }
if($routeNotAllowed) { if ($routeNotAllowed) {
$this->handleException(new RouterException('Route or method not allowed', 403)); $this->handleException(new RouterException('Route or method not allowed', 403));
} }
if($this->loadedRoute === null) { if ($this->loadedRoute === null) {
$this->handleException(new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404)); $this->handleException(new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404));
} }
} }
protected function handleException(\Exception $e) { protected function handleException(\Exception $e)
{
/* @var $handler IExceptionHandler */ /* @var $handler IExceptionHandler */
foreach ($this->exceptionHandlers as $handler) { foreach ($this->exceptionHandlers as $handler) {
$handler = new $handler(); $handler = new $handler();
if (!($handler instanceof IExceptionHandler)) { if (!($handler instanceof IExceptionHandler)) {
@@ -281,7 +279,7 @@ class RouterBase {
$request = $handler->handleError($this->request, $this->loadedRoute, $e); $request = $handler->handleError($this->request, $this->loadedRoute, $e);
if($request !== null && $request->getUri() !== $this->originalUrl && !in_array($request->getUri(), $this->routeRewrites)) { if ($request !== null && $request->getUri() !== $this->originalUrl && !in_array($request->getUri(), $this->routeRewrites)) {
$this->routeRewrites[] = $request->getUri(); $this->routeRewrites[] = $request->getUri();
$this->routeRequest(true); $this->routeRequest(true);
return; return;
@@ -292,9 +290,10 @@ class RouterBase {
throw $e; throw $e;
} }
public function arrayToParams(array $getParams = null, $includeEmpty = true) { public function arrayToParams(array $getParams = null, $includeEmpty = true)
{
if (is_array($getParams) === true && count($getParams) > 0) {
if(is_array($getParams) && count($getParams)) {
if ($includeEmpty === false) { if ($includeEmpty === false) {
$getParams = array_filter($getParams, function ($item) { $getParams = array_filter($getParams, function ($item) {
return (!empty($item)); return (!empty($item));
@@ -307,43 +306,49 @@ class RouterBase {
return ''; return '';
} }
protected function processUrl(RouterRoute $route, $method = null, $parameters = null, $getParams = null) { protected function processUrl(LoadableRoute $route, $method = null, $parameters = null, $getParams = null)
{
$domain = ''; $domain = '';
$parent = $route->getParent(); $parent = $route->getParent();
if($parent !== null && $parent instanceof RouterGroup && count($parent->getDomains())) { $parameters = (array)$parameters;
if ($parent !== null && $parent instanceof RouterGroup && count($parent->getDomains()) > 0) {
$domain = $parent->getDomains(); $domain = $parent->getDomains();
$domain = '//' . $domain[0]; $domain = '//' . $domain[0];
} }
$url = $domain . '/' . trim($route->getUrl(), '/'); $url = $domain . '/' . trim($route->getUrl(), '/');
if($route instanceof IControllerRoute && $method !== null) { if ($route instanceof IControllerRoute && $method !== null) {
$url .= $method;
if(count($parameters)) { $url .= '/' . $method . '/';
$url .= join('/', $parameters);
if (count($parameters) > 0) {
$url .= join('/', (array)$parameters);
} }
} else { } else {
if($parameters !== null && is_array($parameters)) {
$params = array_merge($route->getParameters(), $parameters); if ($parameters !== null && count($parameters) > 0) {
$params = array_merge($route->getParameters(), (array)$parameters);
} else { } else {
$params = $route->getParameters(); $params = $route->getParameters();
} }
$otherParams = array(); $otherParams = array();
$i = 0;
foreach($params as $param => $value) { foreach ($params as $param => $value) {
$value = (isset($parameters[$param])) ? $parameters[$param] : $value; $value = (isset($parameters[$param])) ? $parameters[$param] : $value;
if(stripos($url, '{' . $param. '}') !== false || stripos($url, '{' . $param . '?}') !== false) {
$url = str_ireplace(array('{' . $param . '}', '{' . $param . '?}'), $value, $url); $param1 = $this->parameterModifiers[0] . $param . $this->parameterModifiers[1];
$param2 = $this->parameterModifiers[0] . $param . $this->parameterOptionalSymbol . $this->parameterModifiers[1];
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
$url = str_ireplace([$param1, $param2], $value, $url);
} else { } else {
$otherParams[$param] = $value; $otherParams[$param] = $value;
} }
$i++;
} }
$url = rtrim($url, '/') . '/' . join('/', $otherParams); $url = rtrim($url, '/') . '/' . join('/', $otherParams);
@@ -351,139 +356,129 @@ class RouterBase {
$url = rtrim($url, '/') . '/'; $url = rtrim($url, '/') . '/';
if($getParams !== null) { if ($getParams !== null) {
$url .= $this->arrayToParams($getParams); $url .= $this->arrayToParams($getParams);
} }
return $url; return $url;
} }
public function getRoute($controller = null, $parameters = null, $getParams = null) { /**
* Find route by alias, class, callback or method.
*
* @param string $query
* @return LoadableRoute|null
*/
public function findRoute($query)
{
/* @var $route LoadableRoute */
foreach ($this->controllerUrlMap as $route) {
if($parameters !== null && !is_array($parameters)) { // Check an alias exist, if the matches - use it
throw new \InvalidArgumentException('Invalid type for parameter. Must be array or null'); // Matches either Router alias or controller alias.
if ($route->hasAlias($query)) {
return $route;
} }
if($getParams !== null && !is_array($getParams)) { // Direct match to controller
if ($route instanceof IControllerRoute) {
if (strtolower($route->getController()) === strtolower($query)) {
return $route;
}
}
// Using @ is most definitely a controller@method or alias@method
if (strpos($query, '@') !== false) {
list($controller, $method) = array_map('strtolower', explode('@', $query));
if ($controller === strtolower($route->getClass()) && $method === strtolower($route->getMethod())) {
return $route;
}
}
// Use callback if it's not a function
if (strpos($query, '@') !== false && strpos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) {
if (strtolower($query) === strtolower($route->getClass())) {
return $route;
}
if (strtolower($route->getCallback()) === strtolower($query) || strpos($route->getCallback(), $query) === 0) {
return $route;
}
}
}
return null;
}
public function getRoute($controller = null, $parameters = null, $getParams = null)
{
if ($getParams !== null && is_array($getParams) === false) {
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null'); throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
} }
// Return current route if no options has been specified // Return current route if no options has been specified
if($controller === null && $parameters === null) { if ($controller === null && $parameters === null) {
$getParams = ($getParams !== null && is_array($getParams)) ? array_merge($_GET, $getParams) : $_GET;
$url = parse_url($this->request->getUri(), PHP_URL_PATH); $getParams = ($getParams !== null) ? $getParams : $_GET;
$url = parse_url($this->request->getUri(), PHP_URL_PATH) . $this->arrayToParams($getParams);
if($getParams !== null) {
$url .= $this->arrayToParams($getParams);
}
return $url; return $url;
} }
if($controller === null && $this->loadedRoute !== null) { // If nothing is defined and a route is loaded we use that
if ($controller === null && $this->loadedRoute !== null) {
return $this->processUrl($this->loadedRoute, $this->loadedRoute->getMethod(), $parameters, $getParams); return $this->processUrl($this->loadedRoute, $this->loadedRoute->getMethod(), $parameters, $getParams);
} }
$c = ''; $route = $this->findRoute($controller);
$method = null;
$max = count($this->controllerUrlMap);
/* @var $route RouterRoute */ if ($route !== null) {
for($i = 0; $i < $max; $i++) { return $this->processUrl($route, $route->getMethod(), $parameters, $getParams);
}
$route = $this->controllerUrlMap[$i]; // Using @ is most definitely a controller@method or alias@method
if (stripos($controller, '@') !== false) {
list($controller, $method) = explode('@', $controller);
// Check an alias exist, if the matches - use it /* @var $route LoadableRoute */
if($route instanceof LoadableRoute) { foreach ($this->controllerUrlMap as $route) {
// Check for alias
if ($route->hasAlias($controller)) { if ($route->hasAlias($controller)) {
return $this->processUrl($route, $route->getMethod(), $parameters, $getParams);
}
// Use controller name
if($route instanceof RouterController) {
$c = $route->getController();
} else {
// Use callback if it's not a function
if (stripos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) {
$c = $route->getCallback();
}
}
}
if($c === $controller || strpos($c, $controller) === 0) {
return $this->processUrl($route, $route->getMethod(), $parameters, $getParams);
}
}
$c = '';
// No match has yet been found, let's try to guess what url that should be returned
for($i = 0; $i < $max; $i++) {
$route = $this->controllerUrlMap[$i];
if($route instanceof IControllerRoute) {
$c = $route->getController();
} else if(!is_callable($route->getCallback()) && stripos($route->getCallback(), '@') !== false) {
$c = $route->getClass();
}
if(stripos($controller, '@') !== false) {
$tmp = explode('@', $controller);
$controller = $tmp[0];
$method = $tmp[1];
}
if($controller === $c) {
return $this->processUrl($route, $method, $parameters, $getParams); return $this->processUrl($route, $method, $parameters, $getParams);
} }
// Match controllers either by: "alias @ method" or "controller@method"
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($controller)) {
return $this->processUrl($route, $method, $parameters, $getParams);
} }
$controller = ($controller === null) ? '/' : $controller; }
$url = array($controller); }
if($parameters !== null && is_array($parameters) && count($parameters)) { $url = [($controller === null) ? '/' : $controller];
$url = array_merge($url, $parameters);
if ($parameters !== null && count($parameters) > 0) {
$url = array_merge($url, (array)$parameters);
} }
$url = '/' . trim(join('/', $url), '/') . '/'; $url = '/' . trim(join('/', $url), '/') . '/';
if($getParams !== null) { if ($getParams !== null) {
$url .= $this->arrayToParams($getParams); $url .= $this->arrayToParams($getParams);
} }
return $url; return $url;
} }
/**
* Get default namespace
* @return string
*/
public function getDefaultNamespace(){
return $this->defaultNamespace;
}
/**
* Set the main default namespace that all routes will inherit
* @param string $defaultNamespace
* @return static
*/
public function setDefaultNamespace($defaultNamespace) {
$this->defaultNamespace = $defaultNamespace;
return $this;
}
/** /**
* Get bootmanagers * Get bootmanagers
* @return array * @return array
*/ */
public function getBootManagers() { public function getBootManagers()
{
return $this->bootManagers; return $this->bootManagers;
} }
@@ -491,7 +486,8 @@ class RouterBase {
* Set bootmanagers * Set bootmanagers
* @param array $bootManagers * @param array $bootManagers
*/ */
public function setBootManagers(array $bootManagers) { public function setBootManagers(array $bootManagers)
{
$this->bootManagers = $bootManagers; $this->bootManagers = $bootManagers;
} }
@@ -499,14 +495,16 @@ class RouterBase {
* Add bootmanager * Add bootmanager
* @param RouterBootManager $bootManager * @param RouterBootManager $bootManager
*/ */
public function addBootManager(RouterBootManager $bootManager) { public function addBootManager(RouterBootManager $bootManager)
{
$this->bootManagers[] = $bootManager; $this->bootManagers[] = $bootManager;
} }
/** /**
* @return array * @return array
*/ */
public function getRoutes(){ public function getRoutes()
{
return $this->routes; return $this->routes;
} }
@@ -515,7 +513,8 @@ class RouterBase {
* *
* @return Request * @return Request
*/ */
public function getRequest() { public function getRequest()
{
return $this->request; return $this->request;
} }
@@ -523,7 +522,8 @@ class RouterBase {
* Get response * Get response
* @return Response * @return Response
*/ */
public function getResponse() { public function getResponse()
{
return $this->response; return $this->response;
} }
@@ -531,7 +531,8 @@ class RouterBase {
* Get csrf verifier class * Get csrf verifier class
* @return BaseCsrfVerifier * @return BaseCsrfVerifier
*/ */
public function getCsrfVerifier() { public function getCsrfVerifier()
{
return $this->csrfVerifier; return $this->csrfVerifier;
} }
@@ -541,7 +542,8 @@ class RouterBase {
* @param BaseCsrfVerifier $csrfVerifier * @param BaseCsrfVerifier $csrfVerifier
* @return static * @return static
*/ */
public function setCsrfVerifier(BaseCsrfVerifier $csrfVerifier) { public function setCsrfVerifier(BaseCsrfVerifier $csrfVerifier)
{
$this->csrfVerifier = $csrfVerifier; $this->csrfVerifier = $csrfVerifier;
return $this; return $this;
} }
@@ -550,7 +552,8 @@ class RouterBase {
* Get loaded route * Get loaded route
* @return RouterRoute|null * @return RouterRoute|null
*/ */
public function getLoadedRoute() { public function getLoadedRoute()
{
return $this->loadedRoute; return $this->loadedRoute;
} }
+2 -3
View File
@@ -3,8 +3,7 @@ namespace Pecee\SimpleRouter;
use Pecee\Http\Request; use Pecee\Http\Request;
abstract class RouterBootManager { abstract class RouterBootManager
{
abstract public function boot(Request $request); abstract public function boot(Request $request);
} }
+22 -15
View File
@@ -4,20 +4,21 @@ namespace Pecee\SimpleRouter;
use Pecee\Exception\RouterException; use Pecee\Exception\RouterException;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterController extends LoadableRoute implements IControllerRoute { class RouterController extends LoadableRoute implements IControllerRoute
{
const DEFAULT_METHOD = 'index'; protected $defaultMethod = 'index';
protected $controller; protected $controller;
protected $method; protected $method;
public function __construct($url, $controller) { public function __construct($url, $controller)
{
$this->setUrl($url); $this->setUrl($url);
$this->controller = $controller; $this->controller = $controller;
} }
public function renderRoute(Request $request) { public function renderRoute(Request $request)
if($this->getCallback() !== null && is_callable($this->getCallback())) { {
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
// When the callback is a function // When the callback is a function
call_user_func_array($this->getCallback(), $this->getParameters()); call_user_func_array($this->getCallback(), $this->getParameters());
@@ -41,19 +42,20 @@ class RouterController extends LoadableRoute implements IControllerRoute {
return null; return null;
} }
public function matchRoute(Request $request) { public function matchRoute(Request $request)
{
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH); $url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/'; $url = rtrim($url, '/') . '/';
if(strtolower($url) == strtolower($this->url) || stripos($url, $this->url) === 0) { if (strtolower($url) == strtolower($this->url) || stripos($url, $this->url) === 0) {
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/'); $strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
$path = explode('/', $strippedUrl); $path = explode('/', $strippedUrl);
if(count($path)) { if (count($path) > 0) {
$method = (!isset($path[0]) || trim($path[0]) === '') ? static::DEFAULT_METHOD : $path[0]; $method = (!isset($path[0]) || trim($path[0]) === '') ? $this->defaultMethod : $path[0];
$this->method = $method; $this->method = $method;
array_shift($path); array_shift($path);
@@ -65,13 +67,15 @@ class RouterController extends LoadableRoute implements IControllerRoute {
return true; return true;
} }
} }
return null; return null;
} }
/** /**
* @return string * @return string
*/ */
public function getController() { public function getController()
{
return $this->controller; return $this->controller;
} }
@@ -79,7 +83,8 @@ class RouterController extends LoadableRoute implements IControllerRoute {
* @param string $controller * @param string $controller
* @return static * @return static
*/ */
public function setController($controller) { public function setController($controller)
{
$this->controller = $controller; $this->controller = $controller;
return $this; return $this;
} }
@@ -87,7 +92,8 @@ class RouterController extends LoadableRoute implements IControllerRoute {
/** /**
* @return string * @return string
*/ */
public function getMethod() { public function getMethod()
{
return $this->method; return $this->method;
} }
@@ -95,7 +101,8 @@ class RouterController extends LoadableRoute implements IControllerRoute {
* @param string $method * @param string $method
* @return static * @return static
*/ */
public function setMethod($method) { public function setMethod($method)
{
$this->method = $method; $this->method = $method;
return $this; return $this;
} }
+93 -70
View File
@@ -1,13 +1,12 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
use Pecee\Exception\RouterException; use Pecee\Exception\RouterException;
use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
abstract class RouterEntry { abstract class RouterEntry
{
const REQUEST_TYPE_GET = 'get'; const REQUEST_TYPE_GET = 'get';
const REQUEST_TYPE_POST = 'post'; const REQUEST_TYPE_POST = 'post';
const REQUEST_TYPE_PUT = 'put'; const REQUEST_TYPE_PUT = 'put';
@@ -15,7 +14,7 @@ abstract class RouterEntry {
const REQUEST_TYPE_OPTIONS = 'options'; const REQUEST_TYPE_OPTIONS = 'options';
const REQUEST_TYPE_DELETE = 'delete'; const REQUEST_TYPE_DELETE = 'delete';
public static $allowedRequestTypes = [ public static $requestTypes = [
self::REQUEST_TYPE_GET, self::REQUEST_TYPE_GET,
self::REQUEST_TYPE_POST, self::REQUEST_TYPE_POST,
self::REQUEST_TYPE_PUT, self::REQUEST_TYPE_PUT,
@@ -34,15 +33,17 @@ abstract class RouterEntry {
protected $parameters = array(); protected $parameters = array();
protected $middlewares = array(); protected $middlewares = array();
protected function loadClass($name) { protected function loadClass($name)
if(!class_exists($name)) { {
if (!class_exists($name)) {
throw new RouterException(sprintf('Class %s does not exist', $name)); throw new RouterException(sprintf('Class %s does not exist', $name));
} }
return new $name(); return new $name();
} }
protected function parseParameters($route, $url, $parameterRegex = '[\w]+') { protected function parseParameters($route, $url, $parameterRegex = '[\w]+')
{
$parameterNames = array(); $parameterNames = array();
$regex = ''; $regex = '';
$lastCharacter = ''; $lastCharacter = '';
@@ -50,32 +51,31 @@ abstract class RouterEntry {
$parameter = ''; $parameter = '';
$routeLength = strlen($route); $routeLength = strlen($route);
for($i = 0; $i < $routeLength; $i++) { for ($i = 0; $i < $routeLength; $i++) {
$character = $route[$i]; $character = $route[$i];
if($character === '{') { if ($character === '{') {
// Remove "/" and "\" from regex // Remove "/" and "\" from regex
if(substr($regex, strlen($regex)-1) === '/') { if (substr($regex, strlen($regex) - 1) === '/') {
$regex = substr($regex, 0, strlen($regex) - 2); $regex = substr($regex, 0, strlen($regex) - 2);
} }
$isParameter = true; $isParameter = true;
} elseif($isParameter && $character === '}') { } elseif ($isParameter && $character === '}') {
$required = true; $required = true;
// Check for optional parameter
// Use custom parameter regex if it exists // Check for optional parameter and use custom parameter regex if it exists
if(is_array($this->where) && isset($this->where[$parameter])) { if (is_array($this->where) === true && isset($this->where[$parameter])) {
$parameterRegex = $this->where[$parameter]; $parameterRegex = $this->where[$parameter];
} }
if($lastCharacter === '?') { if ($lastCharacter === '?') {
$parameter = substr($parameter, 0, strlen($parameter)-1); $parameter = substr($parameter, 0, strlen($parameter) - 1);
$regex .= '(?:\/?(?P<' . $parameter . '>'. $parameterRegex .')[^\/]?)?'; $regex .= '(?:\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?)?';
$required = false; $required = false;
} else { } else {
$regex .= '\/?(?P<' . $parameter . '>'. $parameterRegex .')[^\/]?'; $regex .= '\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?';
} }
$parameterNames[] = [ $parameterNames[] = [
@@ -85,10 +85,9 @@ abstract class RouterEntry {
$parameter = ''; $parameter = '';
$isParameter = false; $isParameter = false;
} elseif ($isParameter) {
} elseif($isParameter) {
$parameter .= $character; $parameter .= $character;
} elseif($character === '/') { } elseif ($character === '/') {
$regex .= '\\' . $character; $regex .= '\\' . $character;
} else { } else {
$regex .= str_replace('.', '\\.', $character); $regex .= str_replace('.', '\\.', $character);
@@ -99,21 +98,18 @@ abstract class RouterEntry {
$parameterValues = array(); $parameterValues = array();
if(preg_match('/^'.$regex.'\/?$/is', $url, $parameterValues)) { if (preg_match('/^' . $regex . '\/?$/is', $url, $parameterValues)) {
$parameters = array(); $parameters = array();
$max = count($parameterNames); foreach ($parameterNames as $name) {
for($i = 0; $i < $max; $i++) {
$name = $parameterNames[$i];
$parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null; $parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null;
if($name['required'] && $parameterValue === null) { if ($name['required'] && $parameterValue === null) {
throw new RouterException('Missing required parameter ' . $name['name'], 404); throw new RouterException('Missing required parameter ' . $name['name'], 404);
} }
if(!$name['required'] && $parameterValue === null) { if ($name['required'] === false && $parameterValue === null) {
continue; continue;
} }
@@ -126,9 +122,11 @@ abstract class RouterEntry {
return null; return null;
} }
public function loadMiddleware(Request $request, RouterEntry &$route) { public function loadMiddleware(Request $request, RouterEntry &$route)
if(count($this->getMiddlewares())) { {
foreach($this->getMiddlewares() as $middleware) { if (count($this->getMiddlewares()) > 0) {
foreach ($this->getMiddlewares() as $middleware) {
$middleware = $this->loadClass($middleware); $middleware = $this->loadClass($middleware);
if (!($middleware instanceof IMiddleware)) { if (!($middleware instanceof IMiddleware)) {
throw new RouterException($middleware . ' must be instance of Middleware'); throw new RouterException($middleware . ' must be instance of Middleware');
@@ -136,15 +134,20 @@ abstract class RouterEntry {
/* @var $class IMiddleware */ /* @var $class IMiddleware */
$middleware->handle($request, $route); $middleware->handle($request, $route);
} }
} }
} }
public function renderRoute(Request $request) { public function renderRoute(Request $request)
if($this->getCallback() !== null && is_callable($this->getCallback())) { {
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
// When the callback is a function // When the callback is a function
call_user_func_array($this->getCallback(), $this->getParameters()); call_user_func_array($this->getCallback(), $this->getParameters());
} else { } else {
// When the callback is a method // When the callback is a method
$controller = explode('@', $this->getCallback()); $controller = explode('@', $this->getCallback());
$className = $this->getNamespace() . '\\' . $controller[0]; $className = $this->getNamespace() . '\\' . $controller[0];
@@ -156,7 +159,7 @@ abstract class RouterEntry {
throw new RouterException(sprintf('Method %s does not exist in class %s', $method, $className), 404); throw new RouterException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
} }
$parameters = array_filter($this->getParameters(), function($var){ $parameters = array_filter($this->getParameters(), function ($var) {
return ($var !== null); return ($var !== null);
}); });
@@ -175,8 +178,9 @@ abstract class RouterEntry {
* *
* @return string * @return string
*/ */
public function getIdentifier() { public function getIdentifier()
if(strpos($this->callback, '@') !== false) { {
if (strpos($this->callback, '@') !== false) {
return $this->callback; return $this->callback;
} }
return 'function_' . md5($this->callback); return 'function_' . md5($this->callback);
@@ -188,33 +192,37 @@ abstract class RouterEntry {
* @param array $methods * @param array $methods
* @return static $this * @return static $this
*/ */
public function setRequestMethods(array $methods) { public function setRequestMethods(array $methods)
{
$this->requestMethods = $methods; $this->requestMethods = $methods;
return $this; return $this;
} }
/** /**
* Get allowed request methods * Get allowed request methods
*
* @return array * @return array
*/ */
public function getRequestMethods() { public function getRequestMethods()
{
return $this->requestMethods; return $this->requestMethods;
} }
/** /**
* @return RouterEntry * @return RouterEntry
*/ */
public function getParent() { public function getParent()
{
return $this->parent; return $this->parent;
} }
/** /**
* Set parent route * Set parent route
*
* @param RouterEntry $parent * @param RouterEntry $parent
* @return static $this * @return static $this
*/ */
public function setParent(RouterEntry $parent) { public function setParent(RouterEntry $parent)
{
$this->parent = $parent; $this->parent = $parent;
return $this; return $this;
} }
@@ -223,7 +231,8 @@ abstract class RouterEntry {
* @param string $callback * @param string $callback
* @return static * @return static
*/ */
public function setCallback($callback) { public function setCallback($callback)
{
$this->callback = $callback; $this->callback = $callback;
return $this; return $this;
} }
@@ -231,32 +240,37 @@ abstract class RouterEntry {
/** /**
* @return mixed * @return mixed
*/ */
public function getCallback() { public function getCallback()
{
return $this->callback; return $this->callback;
} }
public function getMethod() { public function getMethod()
if(strpos($this->callback, '@') !== false) { {
if (strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback); $tmp = explode('@', $this->callback);
return $tmp[1]; return $tmp[1];
} }
return null; return null;
} }
public function getClass() { public function getClass()
if(strpos($this->callback, '@') !== false) { {
if (strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback); $tmp = explode('@', $this->callback);
return $tmp[0]; return $tmp[0];
} }
return null; return null;
} }
public function setMethod($method) { public function setMethod($method)
{
$this->callback = sprintf('%s@%s', $this->getClass(), $method); $this->callback = sprintf('%s@%s', $this->getClass(), $method);
return $this; return $this;
} }
public function setClass($class) { public function setClass($class)
{
$this->callback = sprintf('%s@%s', $class, $this->getMethod()); $this->callback = sprintf('%s@%s', $class, $this->getMethod());
return $this; return $this;
} }
@@ -265,12 +279,14 @@ abstract class RouterEntry {
* @param string $middleware * @param string $middleware
* @return static * @return static
*/ */
public function setMiddleware($middleware) { public function setMiddleware($middleware)
{
$this->middlewares[] = $middleware; $this->middlewares[] = $middleware;
return $this; return $this;
} }
public function setMiddlewares(array $middlewares) { public function setMiddlewares(array $middlewares)
{
$this->middlewares = $middlewares; $this->middlewares = $middlewares;
return $this; return $this;
} }
@@ -279,7 +295,8 @@ abstract class RouterEntry {
* @param string $namespace * @param string $namespace
* @return static * @return static
*/ */
public function setNamespace($namespace) { public function setNamespace($namespace)
{
$this->namespace = $namespace; $this->namespace = $namespace;
return $this; return $this;
} }
@@ -287,21 +304,24 @@ abstract class RouterEntry {
/** /**
* @return string|array * @return string|array
*/ */
public function getMiddlewares() { public function getMiddlewares()
{
return $this->middlewares; return $this->middlewares;
} }
/** /**
* @return string * @return string
*/ */
public function getNamespace() { public function getNamespace()
{
return $this->namespace; return $this->namespace;
} }
/** /**
* @return array * @return array
*/ */
public function getParameters(){ public function getParameters()
{
return $this->parameters; return $this->parameters;
} }
@@ -309,7 +329,8 @@ abstract class RouterEntry {
* @param mixed $parameters * @param mixed $parameters
* @return static * @return static
*/ */
public function setParameters($parameters) { public function setParameters($parameters)
{
$this->parameters = $parameters; $this->parameters = $parameters;
return $this; return $this;
} }
@@ -320,7 +341,8 @@ abstract class RouterEntry {
* @param array $options * @param array $options
* @return static * @return static
*/ */
public function where(array $options) { public function where(array $options)
{
$this->where = $options; $this->where = $options;
return $this; return $this;
} }
@@ -331,7 +353,8 @@ abstract class RouterEntry {
* @param string $regex * @param string $regex
* @return static * @return static
*/ */
public function match($regex) { public function match($regex)
{
$this->regex = $regex; $this->regex = $regex;
return $this; return $this;
} }
@@ -341,27 +364,27 @@ abstract class RouterEntry {
* *
* @return array * @return array
*/ */
public function getMergeableData() { public function getMergeableData()
{
$output = array(); $output = array();
if($this->namespace !== null) { if ($this->namespace !== null) {
$output['namespace'] = $this->namespace; $output['namespace'] = $this->namespace;
} }
if(count($this->middlewares)) { if (count($this->middlewares) > 0) {
$output['middleware'] = $this->middlewares; $output['middleware'] = $this->middlewares;
} }
if(count($this->where)) { if (count($this->where) > 0) {
$output['where'] = $this->where; $output['where'] = $this->where;
} }
if(count($this->requestMethods)) { if (count($this->requestMethods) > 0) {
$output['method'] = $this->requestMethods; $output['method'] = $this->requestMethods;
} }
if(count($this->parameters)) { if (count($this->parameters) > 0) {
$output['parameters'] = $this->parameters; $output['parameters'] = $this->parameters;
} }
@@ -374,8 +397,8 @@ abstract class RouterEntry {
* @param array $settings * @param array $settings
* @return static * @return static
*/ */
public function setData(array $settings) { public function setData(array $settings)
{
if (isset($settings['namespace']) && $this->namespace === null) { if (isset($settings['namespace']) && $this->namespace === null) {
$this->setNamespace($settings['namespace']); $this->setNamespace($settings['namespace']);
} }
@@ -385,15 +408,15 @@ abstract class RouterEntry {
$this->middlewares = array_merge((array)$settings['middleware'], $this->middlewares); $this->middlewares = array_merge((array)$settings['middleware'], $this->middlewares);
} }
if(isset($settings['method'])) { if (isset($settings['method'])) {
$this->setRequestMethods((array)$settings['method']); $this->setRequestMethods((array)$settings['method']);
} }
if(isset($settings['where'])) { if (isset($settings['where'])) {
$this->where($settings['where']); $this->where($settings['where']);
} }
if(isset($settings['parameters'])) { if (isset($settings['parameters'])) {
$this->setParameters($settings['parameters']); $this->setParameters($settings['parameters']);
} }
+27 -22
View File
@@ -1,23 +1,22 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterGroup extends RouterEntry { class RouterGroup extends RouterEntry
{
protected $prefix; protected $prefix;
protected $domains = array(); protected $domains = array();
protected $exceptionHandlers = array(); protected $exceptionHandlers = array();
public function matchDomain(Request $request) { public function matchDomain(Request $request)
if(count($this->domains)) { {
for($i = 0; $i < count($this->domains); $i++) { if (count($this->domains) > 0) {
$domain = $this->domains[$i]; foreach ($this->domains as $domain) {
$parameters = $this->parseParameters($domain, $request->getHost(), '.*'); $parameters = $this->parseParameters($domain, $request->getHost(), '.*');
if($parameters !== null) { if ($parameters !== null) {
$this->parameters = $parameters; $this->parameters = $parameters;
return true; return true;
} }
@@ -29,29 +28,34 @@ class RouterGroup extends RouterEntry {
return true; return true;
} }
public function matchRoute(Request $request) { public function matchRoute(Request $request)
{
// Skip if prefix doesn't match // Skip if prefix doesn't match
if($this->prefix !== null && stripos($request->getUri(), $this->prefix) === false) { if ($this->prefix !== null && stripos($request->getUri(), $this->prefix) === false) {
return false; return false;
} }
return $this->matchDomain($request); return $this->matchDomain($request);
} }
public function setExceptionHandlers(array $handlers) { public function setExceptionHandlers(array $handlers)
{
$this->exceptionHandlers = $handlers; $this->exceptionHandlers = $handlers;
return $this; return $this;
} }
public function getExceptionHandlers() { public function getExceptionHandlers()
{
return $this->exceptionHandlers; return $this->exceptionHandlers;
} }
public function getDomains() { public function getDomains()
{
return $this->domains; return $this->domains;
} }
public function setDomains(array $domains) { public function setDomains(array $domains)
{
$this->domains = $domains; $this->domains = $domains;
return $this; return $this;
} }
@@ -60,7 +64,8 @@ class RouterGroup extends RouterEntry {
* @param string $prefix * @param string $prefix
* @return static * @return static
*/ */
public function setPrefix($prefix) { public function setPrefix($prefix)
{
$this->prefix = '/' . trim($prefix, '/'); $this->prefix = '/' . trim($prefix, '/');
return $this; return $this;
} }
@@ -68,26 +73,26 @@ class RouterGroup extends RouterEntry {
/** /**
* @return string * @return string
*/ */
public function getPrefix() { public function getPrefix()
{
return $this->prefix; return $this->prefix;
} }
public function setData(array $settings) { public function setData(array $settings)
{
if(isset($settings['prefix'])) { if (isset($settings['prefix'])) {
$this->setPrefix($settings['prefix']); $this->setPrefix($settings['prefix']);
} }
if(isset($settings['exceptionHandler'])) { if (isset($settings['exceptionHandler'])) {
$this->setExceptionHandlers((array)$settings['exceptionHandler']); $this->setExceptionHandlers((array)$settings['exceptionHandler']);
} }
if(isset($settings['domain'])) { if (isset($settings['domain'])) {
$this->setDomains((array)$settings['domain']); $this->setDomains((array)$settings['domain']);
} }
return parent::setData($settings); return parent::setData($settings);
} }
} }
+28 -20
View File
@@ -4,17 +4,19 @@ namespace Pecee\SimpleRouter;
use Pecee\Exception\RouterException; use Pecee\Exception\RouterException;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterResource extends LoadableRoute implements IControllerRoute { class RouterResource extends LoadableRoute implements IControllerRoute
{
protected $controller; protected $controller;
public function __construct($url, $controller) { public function __construct($url, $controller)
{
$this->setUrl($url); $this->setUrl($url);
$this->controller = $controller; $this->controller = $controller;
} }
public function renderRoute(Request $request) { public function renderRoute(Request $request)
if($this->getCallback() !== null && is_callable($this->getCallback())) { {
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
// When the callback is a function // When the callback is a function
call_user_func_array($this->getCallback(), $this->getParameters()); call_user_func_array($this->getCallback(), $this->getParameters());
} else { } else {
@@ -28,7 +30,7 @@ class RouterResource extends LoadableRoute implements IControllerRoute {
throw new RouterException(sprintf('Method %s does not exist in class %s', $method, $className), 404); throw new RouterException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
} }
call_user_func_array(array($class, $method), $this->getParameters()); call_user_func_array([$class, $method], $this->getParameters());
return $class; return $class;
} }
@@ -36,13 +38,16 @@ class RouterResource extends LoadableRoute implements IControllerRoute {
return null; return null;
} }
protected function call($method, $parameters) { protected function call($method, $parameters)
{
$this->setCallback($this->controller . '@' . $method); $this->setCallback($this->controller . '@' . $method);
$this->parameters = $parameters; $this->parameters = $parameters;
return true; return true;
} }
public function matchRoute(Request $request) { public function matchRoute(Request $request)
{
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH); $url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/'; $url = rtrim($url, '/') . '/';
@@ -50,42 +55,42 @@ class RouterResource extends LoadableRoute implements IControllerRoute {
$parameters = $this->parseParameters($route, $url); $parameters = $this->parseParameters($route, $url);
if($parameters !== null) { if ($parameters !== null) {
if(is_array($parameters)) { $parameters = array_merge($this->parameters, (array)$parameters);
$parameters = array_merge($this->parameters, $parameters);
}
$action = isset($parameters['action']) ? $parameters['action'] : null; $action = isset($parameters['action']) ? $parameters['action'] : null;
unset($parameters['action']); unset($parameters['action']);
$method = request()->getMethod();
// Delete // Delete
if($request->getMethod() === static::REQUEST_TYPE_DELETE && $request->getMethod() === static::REQUEST_TYPE_POST) { if (isset($parameters['id']) && $method === static::REQUEST_TYPE_DELETE) {
return $this->call('destroy', $parameters); return $this->call('destroy', $parameters);
} }
// Update // Update
if(in_array($request->getMethod(), array(static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT)) && $request->getMethod() === static::REQUEST_TYPE_POST) { if (isset($parameters['id']) && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT])) {
return $this->call('update', $parameters); return $this->call('update', $parameters);
} }
// Edit // Edit
if(isset($action) && strtolower($action) === 'edit' && $request->getMethod() === static::REQUEST_TYPE_GET) { if (isset($parameters['id']) && strtolower($action) === 'edit' && $method === static::REQUEST_TYPE_GET) {
return $this->call('edit', $parameters); return $this->call('edit', $parameters);
} }
// Create // Create
if(strtolower($action) === 'create' && $request->getMethod() === static::REQUEST_TYPE_GET) { if (strtolower($action) === 'create' && $method === static::REQUEST_TYPE_GET) {
return $this->call('create', $parameters); return $this->call('create', $parameters);
} }
// Save // Save
if($request->getMethod() === static::REQUEST_TYPE_POST) { if ($method === static::REQUEST_TYPE_POST) {
return $this->call('store', $parameters); return $this->call('store', $parameters);
} }
// Show // Show
if(isset($parameters['id']) && $request->getMethod() === static::REQUEST_TYPE_GET) { if (isset($parameters['id']) && $method === static::REQUEST_TYPE_GET) {
return $this->call('show', $parameters); return $this->call('show', $parameters);
} }
@@ -99,7 +104,8 @@ class RouterResource extends LoadableRoute implements IControllerRoute {
/** /**
* @return string * @return string
*/ */
public function getController() { public function getController()
{
return $this->controller; return $this->controller;
} }
@@ -107,8 +113,10 @@ class RouterResource extends LoadableRoute implements IControllerRoute {
* @param string $controller * @param string $controller
* @return static * @return static
*/ */
public function setController($controller) { public function setController($controller)
{
$this->controller = $controller; $this->controller = $controller;
return $this; return $this;
} }
+10 -10
View File
@@ -1,26 +1,26 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterRoute extends LoadableRoute { class RouterRoute extends LoadableRoute
{
public function __construct($url, $callback) { public function __construct($url, $callback)
{
$this->setUrl($url); $this->setUrl($url);
$this->setCallback($callback); $this->setCallback($callback);
} }
public function matchRoute(Request $request) { public function matchRoute(Request $request)
{
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH); $url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/'; $url = rtrim($url, '/') . '/';
// Match on custom defined regular expression // Match on custom defined regular expression
if($this->regex !== null) { if ($this->regex !== null) {
$parameters = array(); $parameters = array();
if(preg_match('/(' . $this->regex . ')/is', $request->getHost() . $url, $parameters)) { if (preg_match('/(' . $this->regex . ')/is', $request->getHost() . $url, $parameters)) {
$this->parameters = (!is_array($parameters[0]) ? array($parameters[0]) : $parameters[0]); $this->parameters = (array)$parameters[0];
return true; return true;
} }
return null; return null;
@@ -31,7 +31,7 @@ class RouterRoute extends LoadableRoute {
$parameters = $this->parseParameters($route, $url); $parameters = $this->parseParameters($route, $url);
if($parameters !== null) { if ($parameters !== null) {
$this->parameters = array_merge($this->parameters, $parameters); $this->parameters = array_merge($this->parameters, $parameters);
return true; return true;
} }
+228 -39
View File
@@ -1,136 +1,277 @@
<?php <?php
/** /**
* --------------------------- * ---------------------------
* Router helper class * Router helper class
* --------------------------- * ---------------------------
* This class is added so calls can be made statically like Router::get() making the code look more pretty. * This class is added so calls can be made statically like Router::get() making the code look more pretty.
*/ */
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
use Pecee\Exception\RouterException;
use Pecee\Http\Middleware\BaseCsrfVerifier; use Pecee\Http\Middleware\BaseCsrfVerifier;
class SimpleRouter { class SimpleRouter
{
protected static $defaultNamespace;
/** /**
* Start/route request * Start/route request
*
* @throws \Pecee\Exception\RouterException * @throws \Pecee\Exception\RouterException
*/ */
public static function start() { public static function start()
RouterBase::getInstance()->routeRequest(); {
static::router()->routeRequest();
} }
/** /**
* Set default namespace for all routes * Set default namespace which will be prepended to all routes.
*
* @param string $defaultNamespace * @param string $defaultNamespace
*/ */
public static function setDefaultNamespace($defaultNamespace) { public static function setDefaultNamespace($defaultNamespace)
RouterBase::getInstance()->setDefaultNamespace($defaultNamespace); {
static::$defaultNamespace = $defaultNamespace;
} }
/** /**
* Set base csrf verifier * Base CSRF verifier
*
* @param BaseCsrfVerifier $baseCsrfVerifier * @param BaseCsrfVerifier $baseCsrfVerifier
*/ */
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier) { public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier)
RouterBase::getInstance()->setCsrfVerifier($baseCsrfVerifier); {
static::router()->setCsrfVerifier($baseCsrfVerifier);
} }
public static function addBootManager(RouterBootManager $bootManager) { /**
RouterBase::getInstance()->addBootManager($bootManager); * Boot managers allows you to alter the routes before the routing occurs.
* Perfect if you want to load pretty-urls from a file or database.
*
* @param RouterBootManager $bootManager
*/
public static function addBootManager(RouterBootManager $bootManager)
{
static::router()->addBootManager($bootManager);
} }
public static function get($url, $callback, array $settings = null) { /**
* Route the given url to your callback on GET request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function get($url, $callback, array $settings = null)
{
return static::match(['get'], $url, $callback, $settings); return static::match(['get'], $url, $callback, $settings);
} }
public static function post($url, $callback, array $settings = null) { /**
* Route the given url to your callback on POST request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function post($url, $callback, array $settings = null)
{
return static::match(['post'], $url, $callback, $settings); return static::match(['post'], $url, $callback, $settings);
} }
public static function put($url, $callback, array $settings = null) { /**
* Route the given url to your callback on PUT request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function put($url, $callback, array $settings = null)
{
return static::match(['put'], $url, $callback, $settings); return static::match(['put'], $url, $callback, $settings);
} }
public static function patch($url, $callback, array $settings = null) { /**
* Route the given url to your callback on PATCH request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function patch($url, $callback, array $settings = null)
{
return static::match(['patch'], $url, $callback, $settings); return static::match(['patch'], $url, $callback, $settings);
} }
public static function options($url, $callback, array $settings = null) { /**
* Route the given url to your callback on OPTIONS request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function options($url, $callback, array $settings = null)
{
return static::match(['options'], $url, $callback, $settings); return static::match(['options'], $url, $callback, $settings);
} }
public static function delete($url, $callback, array $settings = null) { /**
* Route the given url to your callback on DELETE request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function delete($url, $callback, array $settings = null)
{
return static::match(['delete'], $url, $callback, $settings); return static::match(['delete'], $url, $callback, $settings);
} }
public static function group($settings = array(), $callback) { /**
* Groups allows for encapsulating routes with special settings.
*
* @param array $settings
* @param \Closure $callback
* @throws RouterException
* @return RouterGroup
*/
public static function group($settings = array(), \Closure $callback)
{
$group = new RouterGroup(); $group = new RouterGroup();
$group->setCallback($callback); $group->setCallback($callback);
if($settings !== null && is_array($settings)) { if ($settings !== null && is_array($settings) === true) {
$group->setData($settings); $group->setData($settings);
} }
RouterBase::getInstance()->addRoute($group); if (is_callable($callback) === false) {
throw new RouterException('Invalid callback provided. Only functions or methods supported');
}
static::router()->addRoute($group);
return $group; return $group;
} }
/** /**
* Adds get + post route * Alias for the form method
* *
* @param string $url * @param string $url
* @param callable $callback * @param callable $callback
* @param array|null $settings * @param array|null $settings
* @see SimpleRouter::form
* @return RouterRoute * @return RouterRoute
*/ */
public static function basic($url, $callback, array $settings = null) { public static function basic($url, $callback, array $settings = null)
{
return static::match(['get', 'post'], $url, $callback, $settings); return static::match(['get', 'post'], $url, $callback, $settings);
} }
public static function match(array $requestMethods, $url, $callback, array $settings = null) { /**
* This type will route the given url to your callback on the provided request methods.
* Route the given url to your callback on POST and GET request method.
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @see SimpleRouter::form
* @return RouterRoute
*/
public static function form($url, $callback, array $settings = null)
{
return static::match(['get', 'post'], $url, $callback, $settings);
}
/**
* This type will route the given url to your callback on the provided request methods.
*
* @param array $requestMethods
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterEntry|RouterRoute
*/
public static function match(array $requestMethods, $url, $callback, array $settings = null)
{
$route = new RouterRoute($url, $callback); $route = new RouterRoute($url, $callback);
$route->setRequestMethods($requestMethods); $route->setRequestMethods($requestMethods);
if($settings !== null) { if ($settings !== null) {
$route->setData($settings); $route->setData($settings);
} }
RouterBase::getInstance()->addRoute($route); $route = static::addDefaultNamespace($route);
static::router()->addRoute($route);
return $route; return $route;
} }
public static function all($url, $callback, array $settings = null) { /**
* This type will route the given url to your callback and allow any type of request method
*
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
* @return RouterRoute
*/
public static function all($url, $callback, array $settings = null)
{
$route = new RouterRoute($url, $callback); $route = new RouterRoute($url, $callback);
if($settings !== null) { if ($settings !== null) {
$route->setData($settings); $route->setData($settings);
} }
RouterBase::getInstance()->addRoute($route); $route = static::addDefaultNamespace($route);
static::router()->addRoute($route);
return $route; return $route;
} }
public static function controller($url, $controller, array $settings = null) { /**
* This route will route request from the given url to the controller.
*
* @param string $url
* @param string $controller
* @param array|null $settings
* @return RouterController
*/
public static function controller($url, $controller, array $settings = null)
{
$route = new RouterController($url, $controller); $route = new RouterController($url, $controller);
if($settings !== null) { if ($settings !== null) {
$route->setData($settings); $route->setData($settings);
} }
RouterBase::getInstance()->addRoute($route); $route = static::addDefaultNamespace($route);
static::router()->addRoute($route);
return $route; return $route;
} }
public static function resource($url, $controller, array $settings = null) { /**
* This type will route all REST-supported requests to different methods in the provided controller.
*
* @param string $url
* @param string $controller
* @param array|null $settings
* @return RouterResource
*/
public static function resource($url, $controller, array $settings = null)
{
$route = new RouterResource($url, $controller); $route = new RouterResource($url, $controller);
if($settings !== null) { if ($settings !== null) {
$route->setData($settings); $route->setData($settings);
} }
@@ -139,20 +280,68 @@ class SimpleRouter {
return $route; return $route;
} }
public static function getRoute($controller = null, $parameters = null, $getParams = null) { /**
* Get url by controller or alias.
*
* @param string $controller
* @param array|null $parameters
* @param array|null $getParams
* @return string
*/
public static function getRoute($controller = null, $parameters = null, $getParams = null)
{
return static::router()->getRoute($controller, $parameters, $getParams); return static::router()->getRoute($controller, $parameters, $getParams);
} }
public static function request() { /**
* Get the request
*
* @return \Pecee\Http\Request
*/
public static function request()
{
return static::router()->getRequest(); return static::router()->getRequest();
} }
public static function response() { /**
* Get the response object
*
* @return \Pecee\Http\Response
*/
public static function response()
{
return static::router()->getResponse(); return static::router()->getResponse();
} }
protected static function router() { /**
* Returns the router instance
*
* @return RouterBase
*/
public static function router()
{
return RouterBase::getInstance(); return RouterBase::getInstance();
} }
/**
* Prepends the default namespace to all new routes added.
*
* @param RouterEntry $route
* @return RouterEntry
*/
protected static function addDefaultNamespace(RouterEntry $route)
{
if (static::$defaultNamespace !== null) {
$namespace = static::$defaultNamespace;
if ($route->getNamespace() !== null) {
$namespace .= '\\' . $route->getNamespace();
}
$route->setNamespace($namespace);
}
return $route;
}
} }
+13 -6
View File
@@ -1,18 +1,25 @@
<?php <?php
class DummyController { class DummyController
{
public function start() { public function start()
echo static::class . '@' .'start() OK'; {
echo static::class . '@' . 'start() OK';
} }
public function param($params = null) { public function param($params = null)
{
$params = func_get_args(); $params = func_get_args();
echo 'Params: ' . join(', ', $params); echo 'Params: ' . join(', ', $params);
} }
public function notFound() { public function notFound()
{
echo 'not found'; echo 'not found';
} }
public function silent() {
}
} }
+4 -4
View File
@@ -1,13 +1,13 @@
<?php <?php
require_once 'Exceptions/MiddlewareLoadedException.php'; require_once 'Exceptions/MiddlewareLoadedException.php';
use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
class DummyMiddleware implements IMiddleware { class DummyMiddleware implements IMiddleware
{
public function handle(Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null) { public function handle(Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null)
{
throw new MiddlewareLoadedException('Middleware loaded!'); throw new MiddlewareLoadedException('Middleware loaded!');
} }
@@ -1,2 +1,4 @@
<?php <?php
class MiddlewareLoadedException extends \Exception {} class MiddlewareLoadedException extends \Exception
{
}
+4 -2
View File
@@ -1,7 +1,9 @@
<?php <?php
class ExceptionHandler implements \Pecee\Handler\IExceptionHandler {
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null, \Exception $error){ class ExceptionHandler implements \Pecee\Handler\IExceptionHandler
{
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null, \Exception $error)
{
throw $error; throw $error;
} }
+50 -39
View File
@@ -3,78 +3,89 @@
require_once 'Dummy/DummyMiddleware.php'; require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php'; require_once 'Dummy/DummyController.php';
class GroupTest extends PHPUnit_Framework_TestCase { use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
class GroupTest extends PHPUnit_Framework_TestCase
{
protected $result; protected $result;
public function testGroupLoad() { public function testGroupLoad()
{
$this->result = false; $this->result = false;
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/group'], function() { SimpleRouter::group(['prefix' => '/group'], function () {
$this->result = true; $this->result = true;
}); });
try { try {
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
} catch(Exception $e) { } catch (Exception $e) {
// ignore RouteNotFound exception // ignore RouteNotFound exception
} }
$this->assertTrue($this->result); $this->assertTrue($this->result);
} }
public function testNestedGroup() { public function testNestedGroup()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/api/v1/test'); SimpleRouter::request()->setUri('/api/v1/test');
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/api'], function() { SimpleRouter::group(['prefix' => '/api'], function () {
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/v1'], function() {
\Pecee\SimpleRouter\SimpleRouter::get('/test', 'DummyController@start'); SimpleRouter::group(['prefix' => '/v1'], function () {
}); SimpleRouter::get('/test', 'DummyController@start');
}); });
\Pecee\SimpleRouter\SimpleRouter::start(); });
SimpleRouter::start();
} }
public function testManyRoutes() { public function testManyRoutes()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/match'); SimpleRouter::request()->setUri('/my/match');
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/api'], function() { SimpleRouter::group(['prefix' => '/api'], function () {
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/v1'], function() {
\Pecee\SimpleRouter\SimpleRouter::get('/test', 'DummyController@start'); SimpleRouter::group(['prefix' => '/v1'], function () {
}); SimpleRouter::get('/test', 'DummyController@start');
}); });
\Pecee\SimpleRouter\SimpleRouter::get('/my/match', 'DummyController@start');
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/service'], function() {
\Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/v1'], function() {
\Pecee\SimpleRouter\SimpleRouter::get('/no-match', 'DummyController@start');
});
}); });
\Pecee\SimpleRouter\SimpleRouter::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() { public function testUrls()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/fancy/url/1'); SimpleRouter::request()->setUri('/my/fancy/url/1');
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::get('/my/fancy/url/1', 'DummyController@start', ['as' => 'fancy1']); SimpleRouter::get('/my/fancy/url/1', 'DummyController@start', ['as' => 'fancy1']);
\Pecee\SimpleRouter\SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setAlias('fancy2'); SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setAlias('fancy2');
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
$this->assertTrue((\Pecee\SimpleRouter\SimpleRouter::getRoute('fancy1') === '/my/fancy/url/1/')); $this->assertTrue((SimpleRouter::getRoute('fancy1') === '/my/fancy/url/1/'));
$this->assertTrue((\Pecee\SimpleRouter\SimpleRouter::getRoute('fancy2') === '/my/fancy/url/2/')); $this->assertTrue((SimpleRouter::getRoute('fancy2') === '/my/fancy/url/2/'));
} }
+12 -11
View File
@@ -4,28 +4,29 @@ require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php'; require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php'; require_once 'Dummy/Handler/ExceptionHandler.php';
class MiddlewareTest extends PHPUnit_Framework_TestCase { use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
public function testMiddlewareFound() { class MiddlewareTest extends PHPUnit_Framework_TestCase
{
public function testMiddlewareFound()
{
SimpleRouter::router()->reset();
SimpleRouter::request()->setMethod('get');
SimpleRouter::request()->setUri('/my/test/url');
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () {
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']);
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url');
\Pecee\SimpleRouter\SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function() {
\Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']);
}); });
$found = false; $found = false;
try { try {
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
}catch(\Exception $e) { } catch (\Exception $e) {
$found = ($e instanceof MiddlewareLoadedException); $found = ($e instanceof MiddlewareLoadedException);
} }
$this->assertTrue($found); $this->assertTrue($found);
} }
} }
+78 -76
View File
@@ -4,132 +4,134 @@ require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php'; require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php'; require_once 'Dummy/Handler/ExceptionHandler.php';
class RouterRouteTest extends PHPUnit_Framework_TestCase { use Pecee\SimpleRouter\SimpleRouter as SimpleRouter;
class RouterRouteTest extends PHPUnit_Framework_TestCase
{
protected $result = false; protected $result = false;
public function testNotFound() { public function testNotFound()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/test-param1-param2'); SimpleRouter::request()->setMethod('get');
SimpleRouter::request()->setUri('/test-param1-param2');
\Pecee\SimpleRouter\SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function() { SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () {
\Pecee\SimpleRouter\SimpleRouter::get('/non-existing-path', 'DummyController@start'); SimpleRouter::get('/non-existing-path', 'DummyController@start');
}); });
$found = false; $found = false;
try { try {
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
}catch(\Exception $e) { } catch (\Exception $e) {
$found = ($e instanceof \Pecee\Exception\RouterException && $e->getCode() == 404); $found = ($e instanceof \Pecee\Exception\RouterException && $e->getCode() == 404);
} }
$this->assertTrue($found); $this->assertTrue($found);
} }
public function testGet() { public function testGet()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setUri('/my/test/url');
SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start'); SimpleRouter::get('/my/test/url', 'DummyController@start');
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
} }
public function testPost() { public function testPost()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('post'); SimpleRouter::request()->setUri('/my/test/url');
SimpleRouter::request()->setMethod('post');
\Pecee\SimpleRouter\SimpleRouter::post('/my/test/url', 'DummyController@start'); SimpleRouter::post('/my/test/url', 'DummyController@start');
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
} }
public function testPut() { public function testPut()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('put'); SimpleRouter::request()->setUri('/my/test/url');
SimpleRouter::request()->setMethod('put');
\Pecee\SimpleRouter\SimpleRouter::put('/my/test/url', 'DummyController@start'); SimpleRouter::put('/my/test/url', 'DummyController@start');
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
} }
public function testDelete() { public function testDelete()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('delete'); SimpleRouter::request()->setUri('/my/test/url');
SimpleRouter::request()->setMethod('delete');
\Pecee\SimpleRouter\SimpleRouter::delete('/my/test/url', 'DummyController@start');
\Pecee\SimpleRouter\SimpleRouter::start();
SimpleRouter::delete('/my/test/url', 'DummyController@start');
SimpleRouter::start();
} }
public function testMethodNotAllowed() { public function testMethodNotAllowed()
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); {
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/my/test/url'); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('post'); SimpleRouter::request()->setUri('/my/test/url');
SimpleRouter::request()->setMethod('post');
\Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start'); SimpleRouter::get('/my/test/url', 'DummyController@start');
try { try {
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
} catch(\Exception $e) { } catch (\Exception $e) {
$this->assertEquals(403, $e->getCode()); $this->assertEquals(403, $e->getCode());
} }
} }
public function testSimpleParam() { public function testSimpleParam()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/test-param1'); SimpleRouter::request()->setUri('/test-param1');
\Pecee\SimpleRouter\SimpleRouter::get('/test-{param1}', 'DummyController@param');
\Pecee\SimpleRouter\SimpleRouter::start();
SimpleRouter::get('/test-{param1}', 'DummyController@param');
SimpleRouter::start();
} }
public function testMultiParam() { public function testMultiParam()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/test-param1-param2'); SimpleRouter::request()->setUri('/test-param1-param2');
\Pecee\SimpleRouter\SimpleRouter::get('/test-{param1}-{param2}', 'DummyController@param');
\Pecee\SimpleRouter\SimpleRouter::start();
SimpleRouter::get('/test-{param1}-{param2}', 'DummyController@param');
SimpleRouter::start();
} }
public function testPathParamRegex() { public function testPathParamRegex()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/test/path/123123'); SimpleRouter::request()->setUri('/test/path/123123');
\Pecee\SimpleRouter\SimpleRouter::get('/test/path/{myParam}', 'DummyController@param', ['where' => ['myParam' => '([0-9]+)']]);
\Pecee\SimpleRouter\SimpleRouter::start();
SimpleRouter::get('/test/path/{myParam}', 'DummyController@param', ['where' => ['myParam' => '([0-9]+)']]);
SimpleRouter::start();
} }
public function testDomainRoute() { public function testDomainRoute()
{
\Pecee\SimpleRouter\RouterBase::getInstance()->reset(); SimpleRouter::router()->reset();
\Pecee\SimpleRouter\SimpleRouter::request()->setMethod('get'); SimpleRouter::request()->setMethod('get');
\Pecee\SimpleRouter\SimpleRouter::request()->setUri('/test'); SimpleRouter::request()->setUri('/test');
\Pecee\SimpleRouter\SimpleRouter::request()->setHost('hello.world.com'); SimpleRouter::request()->setHost('hello.world.com');
$this->result = false; $this->result = false;
\Pecee\SimpleRouter\SimpleRouter::group(['domain' => '{subdomain}.world.com'], function() { SimpleRouter::group(['domain' => '{subdomain}.world.com'], function () {
\Pecee\SimpleRouter\SimpleRouter::get('test', function($subdomain = null) { SimpleRouter::get('test', function ($subdomain = null) {
$this->result = ($subdomain === 'hello'); $this->result = ($subdomain === 'hello');
}); });
}); });
\Pecee\SimpleRouter\SimpleRouter::start(); SimpleRouter::start();
$this->assertTrue($this->result); $this->assertTrue($this->result);
+83
View File
@@ -0,0 +1,83 @@
<?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($controller = null, $parameters = null, $getParams = null) {
return SimpleRouter::getRoute($controller, $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::group(['prefix' => '/admin'], function() {
// Match route with prefix on alias
SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'admin.home']);
// Match controller with prefix and alias
SimpleRouter::controller('/users', 'DummyController', ['as' => 'admin.users']);
// Match controller with prefix and NO alias
SimpleRouter::controller('/pages', 'DummyController');
});
// Match controller with no prefix and no alias
SimpleRouter::controller('/cats', 'CatsController');
// Pretend to load page
SimpleRouter::start();
// Should match /
$this->assertEquals($this->getUrl('home'), '/');
// Should match /admin/
$this->assertEquals($this->getUrl('DummyController@start'), '/admin/');
// Should match /admin/
$this->assertEquals($this->getUrl('admin.home'), '/admin/');
// Should match /admin/2/
$this->assertEquals($this->getUrl('admin.home', ['id' => 2]), '/admin/2/');
// Should match /admin/users/
$this->assertEquals($this->getUrl('admin.users'), '/admin/users/');
// Should match /admin/users/home/
$this->assertEquals($this->getUrl('admin.users@home'), '/admin/users/home/');
// Should match /cats/
$this->assertEquals($this->getUrl('CatsController'), '/cats/');
// Should match /cats/view/
$this->assertEquals($this->getUrl('CatsController', 'view'), '/cats/view/');
// Should match /cats/view/
$this->assertEquals($this->getUrl('CatsController', ['view']), '/cats/view/');
// Should match /cats/view/666
$this->assertEquals($this->getUrl('CatsController@view', ['666']), '/cats/view/666/');
// Should match /funny/man/
$this->assertEquals($this->getUrl('/funny/man'), '/funny/man/');
// Should match /?jackdaniels=true
$this->assertEquals($this->getUrl('home', null, ['jackdaniels' => 'true']), '/?jackdaniels=true');
}
}