Compare commits

..

35 Commits

Author SHA1 Message Date
Simon Sessingø e8e1471bab Merge pull request #194 from skipperbent/v2-development
Input optimisations
2016-11-26 05:22:02 +01:00
Simon Sessingø 4de1498723 Merge pull request #192 from skipperbent/v2-development
V2 development
2016-11-26 05:03:36 +01:00
Simon Sessingø ea243f2c89 Merge pull request #190 from skipperbent/v2-development
Development
2016-11-25 18:28:26 +01:00
Simon Sessingø 56653568e4 Merge pull request #188 from skipperbent/v2-development
Development
2016-11-25 12:55:08 +01:00
Simon Sessingø 5d330643e7 Merge pull request #186 from skipperbent/v2-development
Development
2016-11-25 03:28:49 +02:00
Simon Sessingø 57aa8eac1e Merge pull request #184 from skipperbent/v2-development
Fixed Exception when using Request
2016-11-25 03:05:17 +02:00
Simon Sessingø 4efc72d013 Merge pull request #182 from skipperbent/v2-development
Development
2016-11-25 02:58:43 +02:00
Simon Sessingø 49fc991f9a Merge pull request #180 from skipperbent/v2-development
Updated documentation
2016-11-24 14:51:07 +02:00
Simon Sessingø 20353c6e4d Merge pull request #178 from skipperbent/v2-development
Updated documentation to use Demo instead of MyWebsite
2016-11-24 14:44:56 +02:00
Simon Sessingø 4c62f86a26 Merge pull request #176 from skipperbent/v2-development
Fixed HttpException not thrown as NotFoundHttpException
2016-11-24 13:18:52 +02:00
Simon Sessingø 6445746324 Merge pull request #174 from skipperbent/v2-development
Optimisations + bugfixes
2016-11-24 11:05:57 +02:00
Simon Sessingø 1a2921acb4 Merge pull request #173 from skipperbent/v2-development
Development
2016-11-21 09:30:58 +02:00
Simon Sessingø 258d9d05c7 Merge pull request #171 from skipperbent/v2-development
Enhancements
2016-11-21 09:04:22 +02:00
Simon Sessingø 7e7319de06 Merge pull request #169 from skipperbent/v2-development
Fixed // on currentRoute urls.
2016-11-21 05:27:53 +02:00
Simon Sessingø 531b35532b Merge pull request #167 from skipperbent/v2-development
Bugfixes
2016-11-21 05:07:59 +02:00
Simon Sessingø c258f937e8 Merge pull request #165 from skipperbent/v2-development
V 2.4.0 development
2016-11-21 04:09:26 +02:00
Simon Sessingø 88d58cd7b7 Merge pull request #163 from skipperbent/v2-development
Fixed: wrong argument-type in getUrl method
2016-11-19 21:12:57 +02:00
Simon Sessingø d04c74ccad Merge pull request #161 from skipperbent/v2-development
V2 development
2016-11-19 20:41:26 +02:00
Simon Sessingø 02809a4daf Merge pull request #159 from skipperbent/v2-development
Bugfixes
2016-11-19 10:15:56 +02:00
Simon Sessingø da6b5af19f Merge pull request #157 from skipperbent/v2-development
Bugfixes
2016-11-19 09:47:19 +02:00
Simon Sessingø 914ec9d1b7 Merge pull request #155 from skipperbent/v2-development
Small optimisations
2016-11-19 07:02:23 +02:00
Simon Sessingø 5f72755a98 Merge pull request #153 from skipperbent/v2-development
V2 development
2016-11-19 06:25:08 +02:00
Simon Sessingø 41d15d3acd Merge pull request #151 from skipperbent/v2-development
Re-added missing methods from version 1.
2016-11-17 19:01:17 +02:00
Simon Sessingø ded9c8ebe0 Merge pull request #149 from skipperbent/v2-development
Updated documentation
2016-11-17 17:33:49 +02:00
Simon Sessingø 394f7beb8b Merge pull request #147 from skipperbent/v2-development
V2 development
2016-11-17 17:25:30 +02:00
Simon Sessingø baab004482 Merge pull request #145 from skipperbent/v2-development
Added default null parameter value to RouterController and RouterResource
2016-11-17 16:04:38 +02:00
Simon Sessingø 00c0cad211 Merge pull request #143 from skipperbent/v2-development
Bugfix: set parameters to null when new url is set
2016-11-17 15:21:24 +02:00
Simon Sessingø c6e85676da Merge pull request #141 from skipperbent/v2-development
Bugfixes
2016-11-17 06:37:03 +02:00
Simon Sessingø 5a74c9d27d Merge pull request #139 from skipperbent/v2-development
Development
2016-11-17 05:03:30 +02:00
Simon Sessingø b5eef6f3ee Merge pull request #137 from skipperbent/v2-development
Bugfixes
2016-11-16 16:16:22 +02:00
Simon Sessingø ad0eceb814 Merge pull request #135 from skipperbent/v2-development
Bugfixes
2016-11-16 15:32:32 +02:00
Simon Sessingø 4bec2bc5fb Merge pull request #133 from skipperbent/v2-development
Csrf bugfixes
2016-11-15 09:46:54 +02:00
Simon Sessingø 4f47463497 Merge pull request #131 from skipperbent/v2-development
V2 development
2016-11-15 08:13:09 +02:00
Simon Sessingø e5c86c1822 Merge pull request #129 from skipperbent/v2-development
Bugfixes
2016-11-15 01:12:41 +02:00
Simon Sessingø 32c305bd2c Merge pull request #124 from skipperbent/v2-development
V2 development
2016-11-08 18:22:49 +02:00
16 changed files with 353 additions and 301 deletions
+18 -8
View File
@@ -51,13 +51,15 @@ class Input
}
/* Parse get requests */
if (count($_FILES) > 0) {
$this->file = $this->parseFiles();
}
$this->file = $this->parseFiles();
}
public function parseFiles()
{
if (count($_FILES) === 0) {
return [];
}
$list = [];
foreach ($_FILES as $key => $value) {
@@ -267,21 +269,29 @@ class Input
*/
public function all(array $filter = null)
{
$output = $_GET;
$output = $_POST;
if ($this->request->getMethod() === 'post') {
$contents = file_get_contents('php://input');
if (strpos(trim($contents), '{') === 0) {
$post = json_decode($contents, true);
if ($post !== false) {
$output = array_merge($output, $post);
$output = json_decode($contents, true);
if ($output === false) {
$output = [];
}
}
}
return ($filter !== null) ? array_intersect_key($output, array_flip($filter)) : $output;
$output = array_merge($_GET, $output);
if ($filter !== null) {
$output = array_filter($output, function ($key) use ($filter) {
return (in_array($key, $filter) === true);
}, ARRAY_FILTER_USE_KEY);
}
return $output;
}
}
+4 -3
View File
@@ -42,13 +42,14 @@ class InputFile implements IInputItem
'error' => null,
], $values);
return (new static($values['index']))
->setError($values['error'])
$input = new static($values['index']);
$input->setError($values['error'])
->setSize($values['size'])
->setType($values['type'])
->setTmpName($values['tmp_name'])
->setFilename($values['name']);
return $input;
}
/**
@@ -127,7 +128,7 @@ class InputFile implements IInputItem
*/
public function getExtension()
{
return pathinfo($this->getFilename(), PATHINFO_EXTENSION);
return pathinfo($this->getName(), PATHINFO_EXTENSION);
}
/**
@@ -58,7 +58,7 @@ class BaseCsrfVerifier implements IMiddleware
public function handle(Request $request, ILoadableRoute &$route = null)
{
if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete'], false) === true) {
if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete']) === true) {
$token = $request->getInput()->get(static::POST_KEY, null, 'post');
+2 -2
View File
@@ -18,7 +18,7 @@ class Request
$this->host = $this->getHeader('http-host');
$this->uri = $this->getHeader('request-uri');
$this->input = new Input($this);
$this->method = strtolower($this->input->get('_method', $this->getHeader('request-method')));
$this->method = strtolower($this->input->get('_method', $this->getHeader('request-method'), 'post'));
}
protected function parseHeaders()
@@ -215,7 +215,7 @@ class Request
public function __isset($name)
{
return array_key_exists($name, $this->data);
return $this->data[$name] ?? null;
}
public function __set($name, $value = null)
+6 -13
View File
@@ -1,5 +1,4 @@
<?php
namespace Pecee\Http;
class Response
@@ -83,20 +82,14 @@ class Response
}
/**
* Json encode
* @param array|\JsonSerializable $value
* @param int $options JSON options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR.
* @param int $dept JSON debt.
* @throws \InvalidArgumentException
* Json encode array
* @param array $value
*/
public function json($value, $options = null, $dept = 512)
public function json(array $value)
{
if (($value instanceof \JsonSerializable) === false && is_array($value) === false) {
throw new \InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
}
$this->header('Content-Type: application/json; charset=utf-8');
echo json_encode($value, $options, $dept);
exit(0);
$this->header('Content-Type: application/json');
echo json_encode($value);
die();
}
/**
@@ -51,19 +51,4 @@ interface ILoadableRoute extends IRoute
*/
public function setName($name);
/**
* Get regular expression match used for matching route (if defined).
*
* @return string
*/
public function getMatch();
/**
* Add regular expression match for the entire route.
*
* @param string $regex
* @return static
*/
public function setMatch($regex);
}
+16 -2
View File
@@ -18,8 +18,7 @@ interface IRoute
* Returns class to be rendered.
*
* @param Request $request
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @return void
* @return \Closure|string
*/
public function renderRoute(Request $request);
@@ -113,6 +112,21 @@ interface IRoute
public function getDefaultNamespace();
/**
* Get regular expression match used for matching route (if defined).
*
* @return string
*/
public function getMatch();
/**
* Add regular expression match for the entire route.
*
* @param string $regex
* @return static
*/
public function setMatch($regex);
/**
* Get parameter names.
*
+25 -65
View File
@@ -7,8 +7,10 @@ use Pecee\SimpleRouter\Exceptions\HttpException;
abstract class LoadableRoute extends Route implements ILoadableRoute
{
const PARAMETERS_REGEX_MATCH = '%s([\w\-\_]*?)\%s{0,1}%s';
/**
* @var string
* @var
*/
protected $url;
@@ -17,8 +19,6 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
*/
protected $name;
protected $regex;
/**
* Loads and renders middlewares-classes
*
@@ -37,7 +37,6 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
$middleware = $this->getMiddlewares()[$i];
$middleware = $this->loadClass($middleware);
if (!($middleware instanceof IMiddleware)) {
throw new HttpException($middleware . ' must be instance of Middleware');
}
@@ -47,28 +46,6 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
}
}
public function matchRegex(Request $request, $url)
{
/* Match on custom defined regular expression */
if ($this->regex === null) {
return null;
}
$parameters = [];
if (preg_match($this->regex, $request->getHost() . $url, $parameters) > 0) {
/* Remove global match */
$this->parameters = array_slice($parameters, 1);
return true;
}
return false;
}
/**
* Set url
*
@@ -84,8 +61,15 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
$this->parameters = array_fill_keys($matches[1], null);
$max = count($matches[1]);
for ($i = 0; $i < $max; $i++) {
$this->parameters[$matches[1][$i]] = null;
}
}
}
return $this;
@@ -107,38 +91,39 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
*/
public function findUrl($method = null, $parameters = null, $name = null)
{
$url = $this->getUrl();
$url = '';
$parameters = (array)$parameters;
if ($this->getGroup() !== null && count($this->getGroup()->getDomains()) > 0) {
$url = '//' . $this->getGroup()->getDomains()[0] . $url;
$url .= '//' . $this->getGroup()->getDomains()[0];
}
/* Contains parameters that aren't recognized and will be appended at the end of the url */
$url .= $this->getUrl();
$params = array_merge($this->getParameters(), $parameters);
/* Url that contains parameters that aren't recognized */
$unknownParams = [];
/* Create the param string - {parameter} */
/* Create the param string - {} */
$param1 = $this->paramModifiers[0] . '%s' . $this->paramModifiers[1];
/* Create the param string with the optional symbol - {parameter?} */
/* Create the param string with the optional symbol - {?} */
$param2 = $this->paramModifiers[0] . '%s' . $this->paramOptionalSymbol . $this->paramModifiers[1];
/* Replace any {parameter} in the url with the correct value */
/* Let's parse the values of any {} parameter in the url */
$params = $this->getParameters();
$max = count($params) - 1;
$keys = array_keys($params);
for ($i = $max; $i >= 0; $i--) {
$param = $keys[$i];
$value = $value = ($parameters !== null && array_key_exists($param, $parameters)) ? $parameters[$param] : $params[$param];
$value = $params[$param];
/* If parameter is specifically set to null - use the original-defined value */
if ($value === null && isset($this->originalParameters[$param])) {
$value = $this->originalParameters[$param];
}
$value = isset($parameters[$param]) ? $parameters[$param] : $value;
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
/* Add parameter to the correct position */
$url = str_ireplace([sprintf($param1, $param), sprintf($param2, $param)], $value, $url);
} else {
$unknownParams[$param] = $value;
@@ -147,8 +132,6 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
$url .= join('/', $unknownParams);
return rtrim($url, '/') . '/';
}
@@ -173,29 +156,6 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
return (strtolower($this->name) === strtolower($name));
}
/**
* Add regular expression match for the entire route.
*
* @param string $regex
* @return static
*/
public function setMatch($regex)
{
$this->regex = $regex;
return $this;
}
/**
* Get regular expression match used for matching route (if defined).
*
* @return string
*/
public function getMatch()
{
return $this->regex;
}
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
* Alias for LoadableRoute::setName().
+120 -71
View File
@@ -2,12 +2,11 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
abstract class Route implements IRoute
{
const PARAMETERS_REGEX_MATCH = '%s([\w]+)(\%s?)%s';
const REQUEST_TYPE_GET = 'get';
const REQUEST_TYPE_POST = 'post';
const REQUEST_TYPE_PUT = 'put';
@@ -24,13 +23,6 @@ abstract class Route implements IRoute
self::REQUEST_TYPE_DELETE,
];
/**
* If enabled parameters containing null-value
* will not be passed along to the callback.
*
* @var bool
*/
protected $filterEmptyParams = false;
protected $paramModifiers = '{}';
protected $paramOptionalSymbol = '?';
protected $group;
@@ -40,21 +32,12 @@ abstract class Route implements IRoute
/* Default options */
protected $namespace;
protected $regex;
protected $requestMethods = [];
protected $where = [];
protected $parameters = [];
protected $originalParameters = [];
protected $middlewares = [];
protected function loadClass($name)
{
if (class_exists($name) === false) {
throw new NotFoundHttpException(sprintf('Class %s does not exist', $name), 404);
}
return new $name();
}
public function renderRoute(Request $request)
{
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
@@ -71,68 +54,116 @@ abstract class Route implements IRoute
$class = $this->loadClass($className);
$method = $controller[1];
if (method_exists($class, $method) === false) {
if (!method_exists($class, $method)) {
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
}
$parameters = $this->getParameters();
/* Filter parameters with null-value */
if ($this->filterEmptyParams === true) {
$parameters = array_filter($parameters, function ($var) {
return ($var !== null);
});
}
$parameters = array_filter($this->getParameters(), function ($var) {
return ($var !== null);
});
call_user_func_array([$class, $method], $parameters);
return $class;
}
return null;
}
protected function parseParameters($route, $url, $parameterRegex = '[\w]+')
{
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
$parameterNames = [];
$regex = '';
$lastCharacter = '';
$isParameter = false;
$parameter = '';
$routeLength = strlen($route) - 1;
if (preg_match_all('/' . $regex . '/is', $route, $parameters)) {
for ($i = $routeLength; $i >= 0; $i--) {
$urlParts = preg_split('/((\-?\/?)\{[^}]+\})/is', rtrim($route, '/'));
foreach ($urlParts as $key => $t) {
$regex = '';
if ($key < (count($parameters[1]))) {
$name = $parameters[1][$key];
$regex = isset($this->where[$name]) ? $this->where[$name] : $parameterRegex;
$regex = sprintf('\-?\/?(?P<%s>%s)', $name, $regex) . $parameters[2][$key];
$character = strrev($route)[$i];
if ($character === '{') {
/* Remove "/" and "\" from regex */
if (substr($regex, strlen($regex) - 1) === '/') {
$regex = substr($regex, 0, -2);
}
$urlParts[$key] = preg_quote($t, '/') . $regex;
$isParameter = true;
} elseif ($isParameter && $character === '}') {
$required = true;
/* Check for optional parameter and use custom parameter regex if it exists */
if (is_array($this->where) === true && isset($this->where[$parameter])) {
$parameterRegex = $this->where[$parameter];
}
if ($lastCharacter === '?') {
$parameter = substr($parameter, 0, -1);
$regex .= '(?:\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?)?';
$required = false;
} else {
$regex .= '\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?';
}
$parameterNames[] = [
'name' => $parameter,
'required' => $required,
];
$parameter = '';
$isParameter = false;
} elseif ($isParameter) {
$parameter .= $character;
} elseif ($character === '/') {
$regex .= '\\' . $character;
} else {
$regex .= str_replace('.', '\\.', $character);
}
$urlRegex = join('', $urlParts);
} else {
$urlRegex = preg_quote($route, '/');
$lastCharacter = $character;
}
if (preg_match('/^' . $urlRegex . '(\/?)$/is', $url, $matches) > 0) {
$parameterValues = [];
$values = [];
if (preg_match('/^' . $regex . '\/?$/is', $url, $parameterValues)) {
/* Only take matched parameters with name */
foreach ($parameters[1] as $name) {
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
$parameters = [];
$max = count($parameterNames) - 1;
for ($i = $max; $i >= 0; $i--) {
$name = $parameterNames[$i];
$parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null;
if ($parameterValue === null && $name['required']) {
throw new HttpException('Missing required parameter ' . $name['name'], 404);
}
if ($parameterValue === null && $name['required'] === false) {
continue;
}
$parameters[$name['name']] = $parameterValue;
}
return $values;
return $parameters;
}
return null;
}
protected function loadClass($name)
{
if (!class_exists($name)) {
throw new NotFoundHttpException(sprintf('Class %s does not exist', $name), 404);
}
return new $name();
}
/**
* Returns callback name/identifier for the current route based on the callback.
* Useful if you need to get a unique identifier for the loaded route, for instance
@@ -308,6 +339,29 @@ abstract class Route implements IRoute
return ($this->namespace === null) ? $this->defaultNamespace : $this->namespace;
}
/**
* Add regular expression match for the entire route.
*
* @param string $regex
* @return static
*/
public function setMatch($regex)
{
$this->regex = $regex;
return $this;
}
/**
* Get regular expression match used for matching route (if defined).
*
* @return string
*/
public function getMatch()
{
return $this->regex;
}
/**
* Export route settings to array so they can be merged with another route.
*
@@ -329,6 +383,16 @@ abstract class Route implements IRoute
$values['where'] = $this->where;
}
if (count($this->parameters) > 0) {
/* Ensure the right order + values */
$parameters = (isset($values['parameters']) ? $values['parameters'] : []) + $this->parameters;
$parameters = array_merge($parameters, $this->parameters);
$this->setParameters($parameters);
$values['parameters'] = $parameters;
}
if (count($this->middlewares) > 0) {
$values['middleware'] = $this->middlewares;
}
@@ -402,7 +466,7 @@ abstract class Route implements IRoute
*/
public function where(array $options)
{
return $this->setWhere($options);
return $this->where($options);
}
/**
@@ -412,14 +476,7 @@ abstract class Route implements IRoute
*/
public function getParameters()
{
/* Sort the parameters after the user-defined param order, if any */
$parameters = [];
if (count($this->originalParameters) > 0) {
$parameters = $this->originalParameters;
}
return array_merge($parameters, $this->parameters);
return $this->parameters;
}
/**
@@ -430,15 +487,7 @@ abstract class Route implements IRoute
*/
public function setParameters(array $parameters)
{
/*
* If this is the first time setting parameters we store them so we
* later can organize the array, in case somebody tried to sort the array.
*/
if (count($parameters) > 0 && count($this->originalParameters) === 0) {
$this->originalParameters = $parameters;
}
$this->parameters = array_merge($this->parameters, $parameters);
$this->parameters = $parameters;
return $this;
}
@@ -2,6 +2,7 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class RouteController extends LoadableRoute implements IControllerRoute
{
@@ -34,7 +35,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$method = substr($name, strrpos($name, '.') + 1);
$newName = substr($name, 0, strrpos($name, '.'));
if (in_array($method, $this->names, false) === true && strtolower($this->name) === strtolower($newName)) {
if (in_array($method, $this->names) === true && strtolower($this->name) === strtolower($newName)) {
return true;
}
}
@@ -51,7 +52,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
public function findUrl($method = null, $parameters = null, $name = null)
{
if (strpos($name, '.') !== false) {
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names, false);
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names);
if ($found !== false) {
$method = $found;
}
@@ -60,10 +61,14 @@ class RouteController extends LoadableRoute implements IControllerRoute
$url = '';
$parameters = (array)$parameters;
/* Remove requestType from method-name, if it exists */
if ($method !== null) {
/* Remove requestType from method-name, if it exists */
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));
@@ -83,16 +88,37 @@ class RouteController extends LoadableRoute implements IControllerRoute
return '/' . trim($url, '/') . '/';
}
public function renderRoute(Request $request)
{
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
// When the callback is a function
call_user_func_array($this->getCallback(), $this->getParameters());
} else {
// When the callback is a method
$controller = explode('@', $this->getCallback());
$className = $this->getNamespace() . '\\' . $controller[0];
$class = $this->loadClass($className);
$method = $request->getMethod() . ucfirst($controller[1]);
if (!method_exists($class, $method)) {
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
}
call_user_func_array([$class, $method], $this->getParameters());
return $class;
}
return null;
}
public function matchRoute(Request $request)
{
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/';
/* Match global regular-expression for route */
if ($this->matchRegex($request, $url) === true) {
return true;
}
if (stripos($url, $this->url) === 0 && strtolower($url) === strtolower($this->url)) {
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
@@ -104,7 +130,9 @@ class RouteController extends LoadableRoute implements IControllerRoute
$method = (!isset($path[0]) || trim($path[0]) === '') ? $this->defaultMethod : $path[0];
$this->method = $method;
$this->parameters = array_slice($path, 1);
array_shift($path);
$this->parameters = $path;
// Set callback
$this->setCallback($this->controller . '@' . $this->method);
@@ -113,7 +141,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
}
}
return false;
return null;
}
/**
+13 -14
View File
@@ -18,23 +18,26 @@ class RouteGroup extends Route implements IGroupRoute
*/
public function matchDomain(Request $request)
{
if (count($this->domains) === 0) {
return true;
}
if (count($this->domains) > 0) {
foreach ($this->domains as $domain) {
$max = count($this->domains) - 1;
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
for ($i = $max; $i >= 0; $i--) {
if ($parameters !== null && count($parameters) > 0) {
$domain = $this->domains[$i];
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
$this->parameters = $parameters;
if ($parameters !== null && count($parameters) > 0) {
$this->parameters = array_merge($this->parameters, $parameters);
return true;
return true;
}
}
return false;
}
return false;
return true;
}
/**
@@ -45,7 +48,7 @@ class RouteGroup extends Route implements IGroupRoute
*/
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) {
return false;
}
@@ -172,10 +175,6 @@ class RouteGroup extends Route implements IGroupRoute
$values['as'] = $this->name;
}
if (count($this->parameters) > 0) {
$values['parameters'] = $this->parameters;
}
return array_merge($values, parent::toArray());
}
+70 -48
View File
@@ -2,6 +2,7 @@
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class RouteResource extends LoadableRoute implements IControllerRoute
{
@@ -69,9 +70,34 @@ class RouteResource extends LoadableRoute implements IControllerRoute
return $this->url;
}
protected function call($method)
public function renderRoute(Request $request)
{
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
// When the callback is a function
call_user_func_array($this->getCallback(), $this->getParameters());
} else {
// When the callback is a method
$controller = explode('@', $this->getCallback());
$className = $this->getNamespace() . '\\' . $controller[0];
$class = $this->loadClass($className);
$method = strtolower($controller[1]);
if (!method_exists($class, $method)) {
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
}
call_user_func_array([$class, $method], $this->getParameters());
return $class;
}
return null;
}
protected function call($method, $parameters)
{
$this->setCallback($this->controller . '@' . $method);
$this->parameters = $parameters;
return true;
}
@@ -81,58 +107,54 @@ class RouteResource extends LoadableRoute implements IControllerRoute
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/';
/* Match global regular-expression for route */
$domainMatch = $this->matchRegex($request, $url);
if ($domainMatch !== null) {
return $domainMatch;
}
$route = rtrim($this->url, '/') . '/{id?}/{action?}';
$parameters = $this->parseParameters($route, $url);
if ($parameters === null) {
return false;
if ($parameters !== null) {
$parameters = array_merge($this->parameters, (array)$parameters);
$action = isset($parameters['action']) ? $parameters['action'] : null;
unset($parameters['action']);
$method = $request->getMethod();
// Delete
if ($method === static::REQUEST_TYPE_DELETE && isset($parameters['id'])) {
return $this->call($this->methodNames['destroy'], $parameters);
}
// Update
if (isset($parameters['id']) && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT])) {
return $this->call($this->methodNames['update'], $parameters);
}
// Edit
if ($method === static::REQUEST_TYPE_GET && isset($parameters['id']) && strtolower($action) === 'edit') {
return $this->call($this->methodNames['edit'], $parameters);
}
// Create
if ($method === static::REQUEST_TYPE_GET && strtolower($action) === 'create') {
return $this->call($this->methodNames['create'], $parameters);
}
// Save
if ($method === static::REQUEST_TYPE_POST) {
return $this->call($this->methodNames['store'], $parameters);
}
// Show
if ($method === static::REQUEST_TYPE_GET && isset($parameters['id'])) {
return $this->call($this->methodNames['show'], $parameters);
}
// Index
return $this->call($this->methodNames['index'], $parameters);
}
$this->parameters = (array)$parameters;
$action = isset($this->parameters['action']) ? $this->parameters['action'] : null;
unset($this->parameters['action']);
$method = $request->getMethod();
// Delete
if ($method === static::REQUEST_TYPE_DELETE && isset($this->parameters['id'])) {
return $this->call($this->methodNames['destroy']);
}
// Update
if (isset($this->parameters['id']) && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT], false)) {
return $this->call($this->methodNames['update']);
}
// Edit
if ($method === static::REQUEST_TYPE_GET && isset($this->parameters['id']) && strtolower($action) === 'edit') {
return $this->call($this->methodNames['edit']);
}
// Create
if ($method === static::REQUEST_TYPE_GET && strtolower($action) === 'create') {
return $this->call($this->methodNames['create']);
}
// Save
if ($method === static::REQUEST_TYPE_POST) {
return $this->call($this->methodNames['store']);
}
// Show
if ($method === static::REQUEST_TYPE_GET && isset($this->parameters['id'])) {
return $this->call($this->methodNames['show']);
}
// Index
return $this->call($this->methodNames['index']);
return null;
}
/**
+24 -12
View File
@@ -16,22 +16,34 @@ class RouteUrl extends LoadableRoute
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/';
/* Match global regular-expression for route */
$domainMatch = $this->matchRegex($request, $url);
if ($domainMatch !== null) {
return $domainMatch;
// Match on custom defined regular expression
if ($this->regex !== null) {
$parameters = [];
if (preg_match($this->regex, $request->getHost() . $url, $parameters)) {
/* Remove global match */
if (count($parameters) > 1) {
array_shift($parameters);
$this->parameters = $parameters;
}
return true;
}
return null;
}
/* Make regular expression based on route */
$parameters = $this->parseParameters($this->url, $url);
if ($parameters === null) {
return false;
// Make regular expression based on route
$route = rtrim($this->url, '/') . '/';
$parameters = $this->parseParameters($route, $url);
if ($parameters !== null) {
$this->parameters = array_merge($this->parameters, $parameters);
return true;
}
$this->setParameters($parameters);
return true;
return null;
}
}
+5 -4
View File
@@ -167,7 +167,7 @@ class Router
$route->renderRoute($this->request);
$this->processingRoute = false;
if ($route->matchRoute($this->request) === true) {
if ($route->matchRoute($this->request)) {
/* Add exception handlers */
if (count($route->getExceptionHandlers()) > 0) {
@@ -220,6 +220,7 @@ class Router
$routeNotAllowed = false;
try {
/* Initialize boot-managers */
if (count($this->bootManagers) > 0) {
@@ -245,7 +246,7 @@ class Router
if ($this->csrfVerifier !== null) {
/* Verify csrf token for request */
// Verify csrf token for request
$this->csrfVerifier->handle($this->request);
}
@@ -260,10 +261,10 @@ class Router
$route = $this->processedRoutes[$i];
/* If the route matches */
if ($route->matchRoute($this->request) === true) {
if ($route->matchRoute($this->request)) {
/* Check if request method matches */
if (count($route->getRequestMethods()) > 0 && in_array($this->request->getMethod(), $route->getRequestMethods(), false) === false) {
if (count($route->getRequestMethods()) > 0 && in_array($this->request->getMethod(), $route->getRequestMethods()) === false) {
$routeNotAllowed = true;
continue;
}
+10 -20
View File
@@ -14,26 +14,6 @@ class RouterRouteTest extends PHPUnit_Framework_TestCase
{
protected $result = false;
public function testMultiParam()
{
SimpleRouter::router()->reset();
SimpleRouter::request()->setMethod('get');
SimpleRouter::request()->setUri('/test-param1-param2');
SimpleRouter::get('/test-{param1}-{param2}', function($param1, $param2) {
if($param1 === 'param1' && $param2 === 'param2') {
$this->result = true;
}
});
SimpleRouter::start();
$this->assertTrue($this->result);
}
/**
* Redirects to another route through 3 exception handlers.
*
@@ -138,6 +118,16 @@ class RouterRouteTest extends PHPUnit_Framework_TestCase
SimpleRouter::start();
}
public function testMultiParam()
{
SimpleRouter::router()->reset();
SimpleRouter::request()->setMethod('get');
SimpleRouter::request()->setUri('/test-param1-param2');
SimpleRouter::get('/test-{param1}-{param2}', 'DummyController@param');
SimpleRouter::start();
}
public function testPathParamRegex()
{
SimpleRouter::router()->reset();
-12
View File
@@ -99,16 +99,4 @@ class RouterUrlTest extends PHPUnit_Framework_TestCase
}
public function testRegEx()
{
SimpleRouter::router()->reset();
SimpleRouter::request()->setMethod('get');
SimpleRouter::request()->setUri('/my/custom-path');
SimpleRouter::get('/my/{path}', 'DummyController@start')->where(['path' => '[a-zA-Z\-]+']);
SimpleRouter::start();
}
}