mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 16:57:53 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d330643e7 | |||
| 2dd2d95af5 | |||
| 57aa8eac1e | |||
| 7edee8e6d3 | |||
| 4efc72d013 | |||
| e360fb5438 | |||
| c6bce8a420 | |||
| fb6da37963 | |||
| abe427ff59 | |||
| 49fc991f9a | |||
| b2f23c6c7d | |||
| 20353c6e4d | |||
| 53ece9a7fd | |||
| 4c62f86a26 | |||
| 132cf1a10d | |||
| 6445746324 | |||
| ff1f027bda | |||
| 9418d54c8e | |||
| e4ab14a2cb | |||
| 258e0e0f13 | |||
| 1a2921acb4 | |||
| f1a9a50ee5 | |||
| 258d9d05c7 | |||
| 2cc97c120f | |||
| 7e7319de06 | |||
| 5ad7dcf9fd |
@@ -1,100 +0,0 @@
|
||||
# Simple PHP router demo project
|
||||
|
||||
This project is here to give you a basic understanding of how to setup and using simple-php-router.
|
||||
|
||||
Please note that this demo-project only covers how to integrate the `simple-php-router` in a project without a framework. If you are using some sort of PHP framework in your project the implementation might vary.
|
||||
|
||||
**What we won't cover:**
|
||||
|
||||
- How to setup a solution that fits your need. This is a basic demo to help you get started.
|
||||
- Understanding of MVC; including Controllers, Middlewares or ExceptionHandlers.
|
||||
- How to integrate into third party frameworks.
|
||||
|
||||
**What we cover:**
|
||||
|
||||
- How to get up and running fast - from scratch.
|
||||
- How to get ExceptionHandlers, Middlewares and Controllers working.
|
||||
- How to setup your webservers.
|
||||
|
||||
## Installation
|
||||
|
||||
- Navigate to the `demo-project` folder in terminal and run `composer update` to install the latest version.
|
||||
- Point your webserver to `demo-project/public`.
|
||||
|
||||
### Setting up Nginx
|
||||
|
||||
If you are using Nginx please make sure that url-rewriting is enabled.
|
||||
|
||||
You can easily enable url-rewriting by adding the following configuration for the Nginx configuration-file for the demo-project.
|
||||
|
||||
```
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
```
|
||||
|
||||
### Setting up Apache
|
||||
|
||||
Nothing special is required for Apache to work. We've include the `.htaccess` file in the `public` folder. If rewriting is not working for you, please check that the `mod_rewrite` module (htaccess support) is enabled in the Apache configuration.
|
||||
|
||||
## Folder structure
|
||||
|
||||
| Folder | Description |
|
||||
| ------------- |-------------|
|
||||
| app |Contains projects-specific PHP classes|
|
||||
| public |Public folder which are accessible through the web.|
|
||||
|
||||
## Notes
|
||||
|
||||
The demo project has it's own `Router` class implementation which extends the `SimpleRouter` class with further functionality.
|
||||
This class can be useful adding additional functionality that are required before and after routing occurs or any extra functionality belonging to the router itself.
|
||||
|
||||
In this project we also use our custom router-class to autoload the `routes.php` file from our custom location (`app/routes.php`).
|
||||
|
||||
Please check the `routes.php` file in `demo-project/app` for all the urls/rules available in the project.
|
||||
|
||||
### CSRF-verifier
|
||||
|
||||
For the purpose of this demo, we've added a custom CSRF-verifier middleware called `CsrfVerifier` and disabled CSRF checks for all calls to `/api/*`. This will ensure that CSRF form-checks are not applied when calling our demo api url.
|
||||
|
||||
### Exception handlers
|
||||
|
||||
The included `CustomExceptionHandler` class returns a very basic json response for errors received on calls to `/api/*` or otherwise just a simple formatted error response.
|
||||
|
||||
### Middlewares
|
||||
|
||||
`ApiVerification` class is added to all calls to `/api/*`. This simple class just adds some data to the `Request` object, which is returned in one of the methods in the `ApiController` class. We've added this class to demonstrate that you can use middlewares to ensure that the user has the correct authentication - before router loads the controller itself.
|
||||
|
||||
### Urls
|
||||
|
||||
Please see `routes.php` for all routes and rules.
|
||||
|
||||
| URL |
|
||||
| ------------- |
|
||||
| / |
|
||||
| /api/demo |
|
||||
| /companies |
|
||||
| /companies/[id] |
|
||||
| /contact |
|
||||
|
||||
## The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Simon Sessingø / simple-php-router
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Demo\Controllers;
|
||||
|
||||
class ApiController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
// The variable authenticated is set to true in the ApiVerification middleware class.
|
||||
header('content-type: application/json');
|
||||
|
||||
echo json_encode([
|
||||
'authenticated' => request()->authenticated
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
namespace Demo\Controllers;
|
||||
|
||||
class DefaultController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
// implement
|
||||
echo sprintf('DefaultController -> index (?fun=%s)', input()->get('fun'));
|
||||
}
|
||||
|
||||
public function contact()
|
||||
{
|
||||
echo 'DefaultController -> contact';
|
||||
}
|
||||
|
||||
public function companies($id = null)
|
||||
{
|
||||
echo 'DefaultController -> companies -> id: ' . $id;
|
||||
}
|
||||
|
||||
public function notFound()
|
||||
{
|
||||
echo 'Page not found';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
namespace Demo\Handlers;
|
||||
|
||||
use Pecee\Handlers\IExceptionHandler;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
class CustomExceptionHandler implements IExceptionHandler
|
||||
{
|
||||
public function handleError(Request $request, ILoadableRoute &$route = null, \Exception $error)
|
||||
{
|
||||
|
||||
/* You can use the exception handler to format errors depending on the request and type. */
|
||||
|
||||
if (stripos($request->getUri(), '/api') !== false) {
|
||||
|
||||
response()->json([
|
||||
'error' => $error->getMessage(),
|
||||
'code' => $error->getCode(),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/* The router will throw the NotFoundHttpException on 404 */
|
||||
if($error instanceof NotFoundHttpException) {
|
||||
|
||||
/*
|
||||
* Render your own custom 404-view, rewrite the request to another route,
|
||||
* or simply return the $request object to ignore the error and continue on rendering the route.
|
||||
*
|
||||
* The code below will make the router render our page.notfound route.
|
||||
*/
|
||||
|
||||
$request->setUri(url('page.notfound'));
|
||||
return $request;
|
||||
|
||||
}
|
||||
|
||||
throw $error;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
namespace Demo\Middlewares;
|
||||
|
||||
use Pecee\Http\Middleware\IMiddleware;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
class ApiVerification implements IMiddleware
|
||||
{
|
||||
public function handle(Request $request, ILoadableRoute &$route)
|
||||
{
|
||||
// Do authentication
|
||||
$request->authenticated = true;
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
namespace Demo\Middlewares;
|
||||
|
||||
use Pecee\Http\Middleware\BaseCsrfVerifier;
|
||||
|
||||
class CsrfVerifier extends BaseCsrfVerifier
|
||||
{
|
||||
/**
|
||||
* CSRF validation will be ignored on the following urls.
|
||||
*/
|
||||
protected $except = ['/api/*'];
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Custom router which handles default middlewares, default exceptions and things
|
||||
* that should be happen before and after the router is initialised.
|
||||
*/
|
||||
namespace Demo;
|
||||
|
||||
use Pecee\SimpleRouter\SimpleRouter;
|
||||
|
||||
class Router extends SimpleRouter
|
||||
{
|
||||
public static function start($defaultNamespace = null)
|
||||
{
|
||||
// Load our helpers
|
||||
require_once 'helpers.php';
|
||||
|
||||
// Load our custom routes
|
||||
require_once 'routes.php';
|
||||
|
||||
parent::setDefaultNamespace('\Demo');
|
||||
|
||||
// Do initial stuff
|
||||
parent::start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
use Pecee\SimpleRouter\SimpleRouter;
|
||||
|
||||
function url($controller, $parameters = null, $getParams = null)
|
||||
{
|
||||
SimpleRouter::getUrl($controller, $parameters, $getParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current csrf-token
|
||||
* @return null|string
|
||||
*/
|
||||
function csrf_token()
|
||||
{
|
||||
$token = new \Pecee\CsrfToken();
|
||||
return $token->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request object
|
||||
* @return \Pecee\Http\Request
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return SimpleRouter::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response object
|
||||
* @return \Pecee\Http\Response
|
||||
*/
|
||||
function response()
|
||||
{
|
||||
return SimpleRouter::response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input class
|
||||
* @return \Pecee\Http\Input\Input
|
||||
*/
|
||||
function input()
|
||||
{
|
||||
return SimpleRouter::request()->getInput();
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This file contains all the routes for the project
|
||||
*/
|
||||
|
||||
use Demo\Router;
|
||||
|
||||
Router::csrfVerifier(new \Demo\Middlewares\CsrfVerifier());
|
||||
|
||||
Router::group(['exceptionHandler' => 'Demo\Handlers\CustomExceptionHandler'], function () {
|
||||
|
||||
Router::get('/', 'DefaultController@index')->setName('home');
|
||||
|
||||
Router::get('/contact', 'DefaultController@contact')->setName('contact');
|
||||
|
||||
Router::get('/404', 'DefaultController@notFound')->setName('404');
|
||||
|
||||
Router::basic('/companies/{id?}', 'DefaultController@companies')->setName('companies');
|
||||
|
||||
// Api
|
||||
Router::group(['prefix' => '/api', 'middleware' => 'Demo\Middlewares\ApiVerification'], function () {
|
||||
Router::resource('/demo', 'ApiController');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "pecee/simple-router-demo",
|
||||
"description": "Simple router demo project",
|
||||
"keywords": [
|
||||
"simple-router",
|
||||
"php",
|
||||
"php-simple-router"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"pecee/simple-router": "2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Demo\\": "app/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
RewriteEngine on
|
||||
RewriteCond %{SCRIPT_FILENAME} !-f
|
||||
RewriteCond %{SCRIPT_FILENAME} !-d
|
||||
RewriteCond %{SCRIPT_FILENAME} !-l
|
||||
RewriteRule ^(.*)$ index.php/$1
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
// load composer dependencies
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
// Start the routing
|
||||
\Demo\Router::start();
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
interface IInputItem
|
||||
{
|
||||
|
||||
public function getIndex();
|
||||
|
||||
public function getName();
|
||||
|
||||
public function getValue();
|
||||
|
||||
public function __toString();
|
||||
|
||||
}
|
||||
+189
-149
@@ -6,31 +6,206 @@ use Pecee\Http\Request;
|
||||
class Input
|
||||
{
|
||||
/**
|
||||
* @var \Pecee\Http\Input\InputCollection
|
||||
* @var array
|
||||
*/
|
||||
public $get;
|
||||
public $get = [];
|
||||
|
||||
/**
|
||||
* @var \Pecee\Http\Input\InputCollection
|
||||
* @var array
|
||||
*/
|
||||
public $post;
|
||||
public $post = [];
|
||||
|
||||
/**
|
||||
* @var \Pecee\Http\Input\InputCollection
|
||||
* @var array
|
||||
*/
|
||||
public $file;
|
||||
public $file = [];
|
||||
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
protected $invalidContentType = false;
|
||||
|
||||
protected $invalidContentTypes = [
|
||||
'text/plain',
|
||||
'application/x-www-form-urlencoded',
|
||||
];
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->setGet();
|
||||
$this->setPost();
|
||||
$this->setFile();
|
||||
|
||||
if ($request->getMethod() !== 'get') {
|
||||
|
||||
$requestContentType = $request->getHeader('http-content-type');
|
||||
|
||||
$max = count($this->invalidContentTypes) - 1;
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$contentType = $this->invalidContentType[$i];
|
||||
|
||||
if (stripos($requestContentType, $contentType) === 0) {
|
||||
$this->invalidContentType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->invalidContentType === false) {
|
||||
$this->parseInputs();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function parseInputs()
|
||||
{
|
||||
/* Parse get requests */
|
||||
if (count($_GET) > 0) {
|
||||
$this->get = $this->handleGetPost($_GET);
|
||||
}
|
||||
|
||||
/* Parse post requests */
|
||||
$postVars = $_POST;
|
||||
|
||||
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete']) === true) {
|
||||
parse_str(file_get_contents('php://input'), $postVars);
|
||||
}
|
||||
|
||||
if (count($postVars) > 0) {
|
||||
$this->post = $this->handleGetPost($postVars);
|
||||
}
|
||||
|
||||
/* Parse get requests */
|
||||
|
||||
if (count($_FILES) > 0) {
|
||||
|
||||
$max = count($_FILES) - 1;
|
||||
$keys = array_keys($_FILES);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$key = $keys[$i];
|
||||
$value = $_FILES[$key];
|
||||
|
||||
// Handle array input
|
||||
if (is_array($value['name']) === false) {
|
||||
$values['index'] = $key;
|
||||
$this->file[$key] = InputFile::createFromArray(array_merge($value, $values));
|
||||
continue;
|
||||
}
|
||||
|
||||
$subMax = count($value['name']) - 1;
|
||||
$keys = array_keys($value['name']);
|
||||
$output = [];
|
||||
|
||||
for ($i = $subMax; $i >= 0; $i--) {
|
||||
|
||||
$output[$keys[$i]] = InputFile::createFromArray([
|
||||
'index' => $key,
|
||||
'error' => $value['error'][$keys[$i]],
|
||||
'tmp_name' => $value['tmp_name'][$keys[$i]],
|
||||
'type' => $value['type'][$keys[$i]],
|
||||
'size' => $value['size'][$keys[$i]],
|
||||
'name' => $value['name'][$keys[$i]],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
$this->file[$key] = $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleGetPost($array)
|
||||
{
|
||||
$tmp = [];
|
||||
|
||||
$max = count($array) - 1;
|
||||
$keys = array_keys($array);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$key = $keys[$i];
|
||||
$value = $array[$key];
|
||||
|
||||
// Handle array input
|
||||
if (is_array($value) === false) {
|
||||
$tmp[$key] = new InputItem($key, $value);
|
||||
continue;
|
||||
}
|
||||
|
||||
$subMax = count($value) - 1;
|
||||
$keys = array_keys($value);
|
||||
$output = [];
|
||||
|
||||
for ($i = $subMax; $i >= 0; $i--) {
|
||||
$output[$keys[$i]] = new InputItem($key, $value[$keys[$i]]);
|
||||
}
|
||||
|
||||
$tmp[$key] = $output;
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
public function findPost($index, $default = null)
|
||||
{
|
||||
return isset($this->post[$index]) ? $this->post[$index] : $default;
|
||||
}
|
||||
|
||||
public function findFile($index, $default = null)
|
||||
{
|
||||
return isset($this->file[$index]) ? $this->file[$index] : $default;
|
||||
}
|
||||
|
||||
public function findGet($index, $default = null)
|
||||
{
|
||||
return isset($this->get[$index]) ? $this->get[$index] : $default;
|
||||
}
|
||||
|
||||
public function getObject($index, $default = null, $method = null)
|
||||
{
|
||||
$element = null;
|
||||
|
||||
if ($method === null || strtolower($method) === 'get') {
|
||||
$element = $this->findGet($index);
|
||||
}
|
||||
|
||||
if ($element === null && $method === null || strtolower($method) === 'post') {
|
||||
$element = $this->findPost($index);
|
||||
}
|
||||
|
||||
if ($element === null && $method === null || strtolower($method) === 'file') {
|
||||
$element = $this->findFile($index);
|
||||
}
|
||||
|
||||
return ($element === null) ? $default : $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input element value matching index
|
||||
*
|
||||
* @param string $index
|
||||
* @param string|null $default
|
||||
* @param string|null $method
|
||||
* @return InputItem|string
|
||||
*/
|
||||
public function get($index, $default = null, $method = null)
|
||||
{
|
||||
$input = $this->getObject($index, $default, $method);
|
||||
|
||||
if ($input instanceof InputItem) {
|
||||
return (trim($input->getValue()) === '') ? $default : $input->getValue();
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
public function exists($index)
|
||||
{
|
||||
return ($this->getObject($index) !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,6 +215,10 @@ class Input
|
||||
*/
|
||||
public function all(array $filter = null)
|
||||
{
|
||||
if ($this->invalidContentType === true) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$output = $_POST;
|
||||
|
||||
if ($this->request->getMethod() === 'post') {
|
||||
@@ -49,7 +228,7 @@ class Input
|
||||
if (stripos(trim($contents), '{') === 0) {
|
||||
$output = json_decode($contents, true);
|
||||
if ($output === false) {
|
||||
$output = array();
|
||||
$output = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,143 +248,4 @@ class Input
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getObject($index, $default = 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;
|
||||
|
||||
$element = $this->get->findFirst($index);
|
||||
|
||||
if ($element !== null) {
|
||||
return ($key !== null) ? $element[$key] : $element;
|
||||
}
|
||||
|
||||
if ($this->request->getMethod() !== 'get') {
|
||||
|
||||
$element = $this->post->findFirst($index);
|
||||
if ($element !== null) {
|
||||
return ($key !== null) ? $element[$key] : $element;
|
||||
}
|
||||
|
||||
$element = $this->file->findFirst($index);
|
||||
if ($element !== null) {
|
||||
return ($key !== null) ? $element[$key] : $element;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input element value matching index
|
||||
* @param string $index
|
||||
* @param string|null $default
|
||||
* @return string|null
|
||||
*/
|
||||
public function get($index, $default = null)
|
||||
{
|
||||
$item = $this->getObject($index);
|
||||
|
||||
if ($item !== null) {
|
||||
|
||||
if ($item instanceof InputCollection || $item instanceof InputFile) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
return (trim($item->getValue()) === '') ? $default : $item->getValue();
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function exists($index)
|
||||
{
|
||||
return ($this->getObject($index) !== null);
|
||||
}
|
||||
|
||||
public function setGet()
|
||||
{
|
||||
$this->get = new InputCollection();
|
||||
|
||||
if (count($_GET) > 0) {
|
||||
foreach ($_GET as $key => $get) {
|
||||
if (is_array($get) === false) {
|
||||
$this->get->{$key} = new InputItem($key, $get);
|
||||
continue;
|
||||
}
|
||||
|
||||
$output = new InputCollection();
|
||||
|
||||
foreach ($get as $k => $g) {
|
||||
$output->{$k} = new InputItem($k, $g);
|
||||
}
|
||||
|
||||
$this->get->{$key} = $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setPost()
|
||||
{
|
||||
$this->post = new InputCollection();
|
||||
|
||||
$postVars = $_POST;
|
||||
|
||||
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete']) === true) {
|
||||
parse_str(file_get_contents('php://input'), $postVars);
|
||||
}
|
||||
|
||||
if (count($postVars) > 0) {
|
||||
|
||||
foreach ($postVars as $key => $post) {
|
||||
if (is_array($post) === false) {
|
||||
$this->post->{strtolower($key)} = new InputItem($key, $post);
|
||||
continue;
|
||||
}
|
||||
|
||||
$output = new InputCollection();
|
||||
|
||||
foreach ($post as $k => $p) {
|
||||
$output->{$k} = new InputItem($k, $p);
|
||||
}
|
||||
|
||||
$this->post->{strtolower($key)} = $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setFile()
|
||||
{
|
||||
$this->file = new InputCollection();
|
||||
|
||||
if (count($_FILES) > 0) {
|
||||
foreach ($_FILES as $key => $values) {
|
||||
|
||||
// Handle array input
|
||||
if (is_array($values['name']) === false && trim($values['error']) !== '4') {
|
||||
$values['index'] = $key;
|
||||
$this->file->{strtolower($key)} = InputFile::createFromArray($values);
|
||||
continue;
|
||||
}
|
||||
|
||||
$output = new InputCollection();
|
||||
|
||||
foreach ($values['name'] as $k => $val) {
|
||||
if (trim($val['error'][$k]) !== '4') {
|
||||
$output->{$k} = InputFile::createFromArray([
|
||||
'index' => $k,
|
||||
'error' => $val['error'][$k],
|
||||
'tmp_name' => $val['tmp_name'][$k],
|
||||
'type' => $val['type'][$k],
|
||||
'size' => $val['size'][$k],
|
||||
'name' => $val['name'][$k]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->file->{strtolower($key)} = $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
class InputCollection implements \IteratorAggregate
|
||||
{
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Search for input element matching index.
|
||||
*
|
||||
* @param string $index
|
||||
* @param string|null $default
|
||||
* @return InputItem|mixed
|
||||
*/
|
||||
public function findFirst($index, $default = null)
|
||||
{
|
||||
if (count($this->data) > 0) {
|
||||
|
||||
if (isset($this->data[$index])) {
|
||||
return $this->data[$index];
|
||||
}
|
||||
|
||||
foreach ($this->data as $key => $input) {
|
||||
if (strtolower($index) === strtolower($key)) {
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 && trim($input->getValue()) !== '') {
|
||||
return $input->getValue();
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function getValue($index, $default = null) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $index
|
||||
* @throws \InvalidArgumentException
|
||||
* @return InputItem
|
||||
*/
|
||||
public function __get($index)
|
||||
{
|
||||
$item = $this->findFirst($index);
|
||||
// Ensure that item are always available
|
||||
if ($item === null) {
|
||||
$this->data[$index] = new InputItem($index, null);
|
||||
return $this->data[$index];
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function __set($index, $value)
|
||||
{
|
||||
$this->data[$index] = $value;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator
|
||||
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php
|
||||
* @return \Traversable An instance of an object implementing <b>Iterator</b> or
|
||||
* <b>Traversable</b>
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,39 @@
|
||||
<?php
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
class InputFile extends InputItem
|
||||
class InputFile implements IInputItem
|
||||
{
|
||||
public $index;
|
||||
public $name;
|
||||
public $size;
|
||||
public $type;
|
||||
public $error;
|
||||
public $tmpName;
|
||||
|
||||
public function __construct($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
// Make the name human friendly, by replace _ with space
|
||||
$this->name = ucfirst(str_replace('_', ' ', $this->index));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -60,6 +86,13 @@ class InputFile extends InputItem
|
||||
return file_get_contents($this->tmpName);
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file temp. name
|
||||
* @param string $name
|
||||
@@ -68,6 +101,7 @@ class InputFile extends InputItem
|
||||
public function setTmpName($name)
|
||||
{
|
||||
$this->tmpName = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -79,6 +113,7 @@ class InputFile extends InputItem
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -90,6 +125,7 @@ class InputFile extends InputItem
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -100,10 +136,21 @@ class InputFile extends InputItem
|
||||
*/
|
||||
public function setError($error)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->error = (int)$error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->getTmpName();
|
||||
}
|
||||
|
||||
public function hasError()
|
||||
{
|
||||
return ($this->getError() !== 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from array
|
||||
* @param array $values
|
||||
@@ -111,26 +158,33 @@ class InputFile extends InputItem
|
||||
*/
|
||||
public static function createFromArray(array $values)
|
||||
{
|
||||
if(!isset($values['index'])) {
|
||||
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));
|
||||
$input->setError(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->setTmpName(isset($values['tmp_name']) ? $values['tmp_name'] : null);
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
public function toArray()
|
||||
{
|
||||
return $this->tmpName;
|
||||
return [
|
||||
'tmp_name' => $this->tmpName,
|
||||
'type' => $this->type,
|
||||
'size' => $this->size,
|
||||
'name' => $this->name,
|
||||
'error' => $this->error,
|
||||
];
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace Pecee\Http\Input;
|
||||
|
||||
class InputItem
|
||||
class InputItem implements IInputItem
|
||||
{
|
||||
public $index;
|
||||
public $name;
|
||||
@@ -16,6 +16,14 @@ class InputItem
|
||||
$this->name = ucfirst(str_replace('_', ' ', $this->index));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -32,14 +40,6 @@ class InputItem
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input name
|
||||
* @param string $name
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
namespace Pecee\Http\Middleware;
|
||||
|
||||
use Pecee\CsrfToken;
|
||||
use Pecee\Exceptions\TokenMismatchException;
|
||||
use Pecee\Http\Middleware\Exceptions\TokenMismatchException;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
|
||||
@@ -20,7 +20,7 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
$this->csrfToken = new CsrfToken();
|
||||
|
||||
// Generate or get the CSRF-Token from Cookie.
|
||||
$this->token = (!$this->hasToken()) ? $this->generateToken() : $this->csrfToken->getToken();
|
||||
$this->token = ($this->hasToken() === false) ? $this->generateToken() : $this->csrfToken->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,11 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->except as $url) {
|
||||
$max = count($this->except) - 1;
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
$url = $this->except[$i];
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
if ($url[strlen($url) - 1] === '*') {
|
||||
$url = rtrim($url, '*');
|
||||
@@ -43,7 +47,7 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
$skip = ($url === rtrim($request->getUri(), '/'));
|
||||
}
|
||||
|
||||
if ($skip) {
|
||||
if ($skip === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -54,16 +58,16 @@ class BaseCsrfVerifier implements IMiddleware
|
||||
public function handle(Request $request, ILoadableRoute &$route = null)
|
||||
{
|
||||
|
||||
if ($request->getMethod() !== 'get' && !$this->skip($request)) {
|
||||
if (in_array($request->getMethod(), ['post', 'put', 'delete']) === true && $this->skip($request) === false) {
|
||||
|
||||
$token = $request->getInput()->post->get(static::POST_KEY);
|
||||
$token = $request->getInput()->get(static::POST_KEY, null, 'post');
|
||||
|
||||
// If the token is not posted, check headers for valid x-csrf-token
|
||||
if ($token === null) {
|
||||
$token = $request->getHeader(static::HEADER_KEY);
|
||||
}
|
||||
|
||||
if (!$this->csrfToken->validate($token)) {
|
||||
if ($this->csrfToken->validate($token) === false) {
|
||||
throw new TokenMismatchException('Invalid csrf-token.');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Pecee\Exceptions;
|
||||
namespace Pecee\Http\Middleware\Exceptions;
|
||||
|
||||
class TokenMismatchException extends \Exception
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ use Pecee\Http\Input\Input;
|
||||
|
||||
class Request
|
||||
{
|
||||
protected $data = array();
|
||||
protected $data = [];
|
||||
protected $headers;
|
||||
protected $host;
|
||||
protected $uri;
|
||||
@@ -15,20 +15,27 @@ class Request
|
||||
public function __construct()
|
||||
{
|
||||
$this->parseHeaders();
|
||||
$this->input = new Input($this);
|
||||
$this->host = $this->getHeader('http-host');;
|
||||
$this->uri = $this->getHeader('request-uri');
|
||||
$this->method = strtolower($this->input->post->findFirst('_method', $this->getHeader('request-method')));
|
||||
$this->input = new Input($this);
|
||||
$this->method = $this->input->get('_method', strtolower($this->getHeader('request-method')));
|
||||
}
|
||||
|
||||
protected function parseHeaders()
|
||||
{
|
||||
$this->headers = array();
|
||||
$this->headers = [];
|
||||
|
||||
foreach ($_SERVER as $name => $value) {
|
||||
$this->headers[strtolower($name)] = $value;
|
||||
$this->headers[strtolower(str_replace('_', '-', $name))] = $value;
|
||||
$max = count($_SERVER) - 1;
|
||||
$keys = array_keys($_SERVER);
|
||||
|
||||
for($i = $max; $i >= 0; $i--) {
|
||||
$key = $keys[$i];
|
||||
$value = $_SERVER[$key];
|
||||
|
||||
$this->headers[strtolower($key)] = $value;
|
||||
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function isSecure()
|
||||
@@ -136,7 +143,24 @@ class Request
|
||||
*/
|
||||
public function getHeader($name, $defaultValue = null)
|
||||
{
|
||||
return isset($this->headers[strtolower($name)]) ? $this->headers[strtolower($name)] : $defaultValue;
|
||||
if (isset($this->headers[strtolower($name)])) {
|
||||
return $this->headers[strtolower($name)];
|
||||
}
|
||||
|
||||
$max = count($_SERVER) - 1;
|
||||
$keys = array_keys($_SERVER);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$key = $keys[$i];
|
||||
$name = $_SERVER[$key];
|
||||
|
||||
if ($key === $name) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,13 +66,12 @@ class Response
|
||||
'Etag: ' . $eTag
|
||||
]);
|
||||
|
||||
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
|
||||
) {
|
||||
$httpModified = $this->request->getHeader('http-if-modified-since');
|
||||
$httpIfNoneMatch = $this->request->getHeader('http-if-none-match');
|
||||
|
||||
$this->headers([
|
||||
'HTTP/1.1 304 Not Modified'
|
||||
]);
|
||||
if ($httpModified !== null && strtotime($httpModified) == $lastModified || $httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) {
|
||||
|
||||
$this->header('HTTP/1.1 304 Not Modified');
|
||||
|
||||
exit();
|
||||
}
|
||||
@@ -86,7 +85,7 @@ class Response
|
||||
*/
|
||||
public function json(array $value)
|
||||
{
|
||||
$this->header('Content-type: application/json');
|
||||
$this->header('Content-Type: application/json');
|
||||
echo json_encode($value);
|
||||
die();
|
||||
}
|
||||
@@ -109,8 +108,9 @@ class Response
|
||||
*/
|
||||
public function headers(array $headers)
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
header($header);
|
||||
$max = count($headers);
|
||||
for($i = 0; $i < $max; $i++) {
|
||||
$this->header($headers[$i]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,12 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
public function loadMiddleware(Request $request, ILoadableRoute &$route)
|
||||
{
|
||||
if (count($this->getMiddlewares()) > 0) {
|
||||
foreach ($this->getMiddlewares() as $middleware) {
|
||||
|
||||
$max = count($this->getMiddlewares());
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
|
||||
$middleware = $this->getMiddlewares()[$i];
|
||||
|
||||
$middleware = $this->loadClass($middleware);
|
||||
if (!($middleware instanceof IMiddleware)) {
|
||||
@@ -43,12 +48,21 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
|
||||
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
|
||||
foreach ($matches[1] as $key) {
|
||||
$this->parameters[$key] = null;
|
||||
if(strpos($this->url, $this->paramModifiers[0]) !== false) {
|
||||
|
||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||
|
||||
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
|
||||
|
||||
$max = count($matches[1]);
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
$this->parameters[$matches[1][$i]] = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -92,7 +106,14 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
||||
$param2 = $this->paramModifiers[0] . '%s' . $this->paramOptionalSymbol . $this->paramModifiers[1];
|
||||
|
||||
/* Let's parse the values of any {} parameter in the url */
|
||||
foreach ($params as $param => $value) {
|
||||
|
||||
$max = count($params) - 1;
|
||||
$keys = array_keys($params);
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
$param = $keys[$i];
|
||||
$value = $params[$param];
|
||||
|
||||
$value = (isset($parameters[$param])) ? $parameters[$param] : $value;
|
||||
|
||||
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
|
||||
|
||||
@@ -77,10 +77,11 @@ abstract class Route implements IRoute
|
||||
$lastCharacter = '';
|
||||
$isParameter = false;
|
||||
$parameter = '';
|
||||
$routeLength = strlen($route) - 1;
|
||||
|
||||
for ($i = 0; $i < strlen($route); $i++) {
|
||||
for ($i = $routeLength; $i >= 0; $i--) {
|
||||
|
||||
$character = $route[$i];
|
||||
$character = strrev($route)[$i];
|
||||
|
||||
if ($character === '{') {
|
||||
/* Remove "/" and "\" from regex */
|
||||
@@ -129,7 +130,12 @@ abstract class Route implements IRoute
|
||||
|
||||
$parameters = [];
|
||||
|
||||
foreach ($parameterNames as $name) {
|
||||
$max = count($parameterNames) - 1;
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$name = $parameterNames[$i];
|
||||
|
||||
$parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null;
|
||||
|
||||
if ($name['required'] && $parameterValue === null) {
|
||||
@@ -152,7 +158,7 @@ abstract class Route implements IRoute
|
||||
protected function loadClass($name)
|
||||
{
|
||||
if (!class_exists($name)) {
|
||||
throw new HttpException(sprintf('Class %s does not exist', $name), 500);
|
||||
throw new NotFoundHttpException(sprintf('Class %s does not exist', $name), 404);
|
||||
}
|
||||
|
||||
return new $name();
|
||||
|
||||
@@ -59,12 +59,19 @@ class RouteController extends LoadableRoute implements IControllerRoute
|
||||
|
||||
/* Remove requestType from method-name, if it exists */
|
||||
if ($method !== null) {
|
||||
foreach (static::$requestTypes as $requestType) {
|
||||
|
||||
$max = count(static::$requestTypes);
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
|
||||
$requestType = static::$requestTypes[$i];
|
||||
|
||||
if (stripos($method, $requestType) === 0) {
|
||||
$method = substr($method, strlen($requestType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$method .= '/';
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,12 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
public function matchDomain(Request $request)
|
||||
{
|
||||
if (count($this->domains) > 0) {
|
||||
foreach ($this->domains as $domain) {
|
||||
|
||||
$max = count($this->domains) - 1;
|
||||
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$domain = $this->domains[$i];
|
||||
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
|
||||
|
||||
if ($parameters !== null) {
|
||||
|
||||
@@ -107,7 +107,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
$action = isset($parameters['action']) ? $parameters['action'] : null;
|
||||
unset($parameters['action']);
|
||||
|
||||
$method = request()->getMethod();
|
||||
$method = $request->getMethod();
|
||||
|
||||
// Delete
|
||||
if (isset($parameters['id']) && $method === static::REQUEST_TYPE_DELETE) {
|
||||
|
||||
@@ -19,8 +19,12 @@ class RouteUrl extends LoadableRoute
|
||||
// Match on custom defined regular expression
|
||||
if ($this->regex !== null) {
|
||||
$parameters = [];
|
||||
if (preg_match('/(' . $this->regex . ')/is', $request->getHost() . $url, $parameters)) {
|
||||
$this->parameters = (array)$parameters[0];
|
||||
if (preg_match($this->regex, $request->getHost() . $url, $parameters)) {
|
||||
/* Remove global match */
|
||||
if(count($parameters) > 1) {
|
||||
array_shift($parameters);
|
||||
$this->parameters = $parameters;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,8 +140,12 @@ class Router
|
||||
protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null)
|
||||
{
|
||||
// Loop through each route-request
|
||||
$max = count($routes) - 1;
|
||||
|
||||
/* @var $route IRoute */
|
||||
foreach ($routes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $routes[$i];
|
||||
|
||||
if ($route instanceof IGroupRoute) {
|
||||
|
||||
@@ -208,8 +212,14 @@ class Router
|
||||
|
||||
/* Initialize boot-managers */
|
||||
if (count($this->bootManagers) > 0) {
|
||||
|
||||
$max = count($this->bootManagers) - 1;
|
||||
|
||||
/* @var $manager IRouterBootManager */
|
||||
foreach ($this->bootManagers as $manager) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$manager = $this->bootManagers[$i];
|
||||
|
||||
$this->request = $manager->boot($this->request);
|
||||
|
||||
if (!($this->request instanceof Request)) {
|
||||
@@ -232,8 +242,12 @@ class Router
|
||||
$this->originalUrl = $this->request->getUri();
|
||||
}
|
||||
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route IRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* If the route matches */
|
||||
if ($route->matchRoute($this->request)) {
|
||||
@@ -279,8 +293,12 @@ class Router
|
||||
|
||||
protected function handleException(\Exception $e)
|
||||
{
|
||||
$max = count($this->exceptionHandlers);
|
||||
|
||||
/* @var $handler IExceptionHandler */
|
||||
foreach ($this->exceptionHandlers as $handler) {
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
|
||||
$handler = $this->exceptionHandlers[$i];
|
||||
|
||||
$handler = new $handler();
|
||||
|
||||
@@ -327,8 +345,12 @@ class Router
|
||||
*/
|
||||
public function findRoute($name)
|
||||
{
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
|
||||
if ($route->hasName($name)) {
|
||||
@@ -384,19 +406,23 @@ class Router
|
||||
* @param array|null $getParams
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl($name = null, $parameters = null, $getParams = [])
|
||||
public function getUrl($name = null, $parameters = null, $getParams = null)
|
||||
{
|
||||
if ($getParams !== null && is_array($getParams) === false) {
|
||||
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
||||
}
|
||||
|
||||
if ($getParams === null) {
|
||||
/* Only merge $_GET when all parameters are null */
|
||||
if ($name === null && $parameters === null && $getParams === null) {
|
||||
$getParams = $_GET;
|
||||
} else {
|
||||
$getParams = (array)$getParams;
|
||||
}
|
||||
|
||||
/* Return current route if no options has been specified */
|
||||
if ($name === null && $parameters === null) {
|
||||
return '/' . trim(parse_url($this->request->getUri(), PHP_URL_PATH), '/') . '/' . $this->arrayToParams($getParams);
|
||||
$url = rtrim(parse_url($this->request->getUri(), PHP_URL_PATH), '/');
|
||||
return (($url === '') ? '/' : $url . '/') . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
/* If nothing is defined and a route is loaded we use that */
|
||||
@@ -417,8 +443,12 @@ class Router
|
||||
|
||||
/* Loop through all the routes to see if we can find a match */
|
||||
|
||||
$max = count($this->processedRoutes) - 1;
|
||||
|
||||
/* @var $route ILoadableRoute */
|
||||
foreach ($this->processedRoutes as $route) {
|
||||
for ($i = $max; $i >= 0; $i--) {
|
||||
|
||||
$route = $this->processedRoutes[$i];
|
||||
|
||||
/* Check if the route contains the name/alias */
|
||||
if ($route->hasName($controller)) {
|
||||
@@ -434,8 +464,8 @@ class Router
|
||||
}
|
||||
|
||||
/* No result so we assume that someone is using a hardcoded url and join everything together. */
|
||||
|
||||
return '/' . trim(join('/', array_merge((array)$name, (array)$parameters)), '/') . '/' . $this->arrayToParams($getParams);
|
||||
$url = trim(join('/', array_merge((array)$name, (array)$parameters)), '/');
|
||||
return (($url === '') ? '/' : '/' . $url . '/') . $this->arrayToParams($getParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -311,7 +311,7 @@ class SimpleRouter
|
||||
* @param array|null $getParams
|
||||
* @return string
|
||||
*/
|
||||
public static function getUrl($name = null, $parameters = null, $getParams = [])
|
||||
public static function getUrl($name = null, $parameters = null, $getParams = null)
|
||||
{
|
||||
return static::router()->getUrl($name, $parameters, $getParams);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user