Development

- Optimised Input-classes.
- `get` and `getObject` methods on `Input` now supports filtering on multiple method-types when using the `$method` parameter.
- Input classes now know how to parse that stupid nested $_FILES array.
- It's now possible to change method-names on ResourceControllers.
- Removed `getValue` and `setValue` from `InputFile` classes.
- Ensured that request-method are only parsed from $_POST or $_SERVER.
- Fixed minor parameter-issues with subdomain routing.
- Added PHPDocs.
- Added even more unit-tests.
- Many small optimisations tweaks.
This commit is contained in:
Simon Sessingø
2016-11-26 04:30:00 +01:00
parent 68fc6b76c0
commit 6213f2fb75
27 changed files with 685 additions and 417 deletions

View File

@@ -7,41 +7,41 @@ interface IRestController
/**
* @return void
*/
function index();
public function index();
/**
* @param mixed $id
* @return void
*/
function show($id);
public function show($id);
/**
* @return void
*/
function store();
public function store();
/**
* @return void
*/
function create();
public function create();
/**
* View
* @param mixed $id
* @return void
*/
function edit($id);
public function edit($id);
/**
* @param mixed $id
* @return void
*/
function update($id);
public function update($id);
/**
* @param mixed $id
* @return void
*/
function destroy($id);
public function destroy($id);
}

View File

@@ -12,10 +12,6 @@ interface IInputItem
public function setName($name);
public function getValue();
public function setValue($value);
public function __toString();
}

View File

@@ -32,7 +32,7 @@ class Input
$this->parseInputs();
}
protected function parseInputs()
public function parseInputs()
{
/* Parse get requests */
if (count($_GET) > 0) {
@@ -42,7 +42,7 @@ class Input
/* Parse post requests */
$postVars = $_POST;
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete']) === true) {
if (in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) {
parse_str(file_get_contents('php://input'), $postVars);
}
@@ -51,49 +51,86 @@ class Input
}
/* 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;
}
}
$this->parseFiles();
}
protected function handleGetPost($array)
public function parseFiles()
{
$tmp = [];
if (count($_FILES) === 0) {
return [];
}
$list = [];
foreach ($_FILES as $key => $value) {
// Handle array input
if (is_array($value['name']) === false) {
$values['index'] = $key;
$list[$key] = InputFile::createFromArray(array_merge($value, $values));
continue;
}
$keys = [];
$list = array_merge_recursive($list, [$key => $this->rearrangeFiles($value['name'], $keys, $value)]);
}
return $list;
}
protected function rearrangeFiles(array $values, &$index, $original)
{
$output = [];
$getItem = function ($key, $property = 'name') use ($original, $index) {
$path = $original[$property];
foreach (array_values($index) as $i) {
$path = $path[$i];
}
return $path[$key];
};
foreach ($values as $key => $value) {
if (is_array($getItem($key)) === false) {
$file = InputFile::createFromArray([
'index' => $key,
'error' => $getItem($key, 'error'),
'tmp_name' => $getItem($key, 'tmp_name'),
'type' => $getItem($key, 'type'),
'size' => $getItem($key, 'size'),
'filename' => $getItem($key, 'name'),
]);
$output = array_merge_recursive($output, [$key => $file]);
if (isset($output[$key])) {
$output[$key][] = $file;
} else {
$output[$key] = $file;
}
continue;
}
$index[] = $key;
$output = array_merge_recursive($output, [$key => $this->rearrangeFiles($value, $index, $original)]);
}
return $output;
}
protected function handleGetPost(array $array)
{
$list = [];
$max = count($array) - 1;
$keys = array_keys($array);
@@ -105,77 +142,110 @@ class Input
// Handle array input
if (is_array($value) === false) {
$tmp[$key] = new InputItem($key, $value);
$list[$key] = new InputItem($key, $value);
continue;
}
$subMax = count($value) - 1;
$keys = array_keys($value);
$output = [];
$output = $this->handleGetPost($value);
for ($i = $subMax; $i >= 0; $i--) {
$output[$keys[$i]] = new InputItem($key, $value[$keys[$i]]);
}
$tmp[$key] = $output;
$list[$key] = $output;
}
return $tmp;
return $list;
}
public function findPost($index, $default = null)
/**
* Find post-value by index or return default value.
*
* @param string $index
* @param string|null $defaultValue
* @return InputItem|string
*/
public function findPost($index, $defaultValue = null)
{
return isset($this->post[$index]) ? $this->post[$index] : $default;
return $this->post[$index] ?? $defaultValue;
}
public function findFile($index, $default = null)
/**
* Find file by index or return default value.
*
* @param string $index
* @param string|null $defaultValue
* @return InputFile|string
*/
public function findFile($index, $defaultValue = null)
{
return isset($this->file[$index]) ? $this->file[$index] : $default;
return $this->file[$index] ?? $defaultValue;
}
public function findGet($index, $default = null)
/**
* Find parameter/query-string by index or return default value.
*
* @param string $index
* @param string|null $defaultValue
* @return InputItem|string
*/
public function findGet($index, $defaultValue = null)
{
return isset($this->get[$index]) ? $this->get[$index] : $default;
return $this->get[$index] ?? $defaultValue;
}
public function getObject($index, $default = null, $method = null)
/**
* Get input object
*
* @param string $index
* @param string|null $defaultValue
* @param array|string|null $methods
* @return IInputItem|string
*/
public function getObject($index, $defaultValue = null, $methods = null)
{
if ($methods !== null && is_string($methods) === true) {
$methods = [$methods];
}
$element = null;
if ($method === null || strtolower($method) === 'get') {
if ($methods === null || in_array('get', $methods)) {
$element = $this->findGet($index);
}
if ($element === null && $method === null || strtolower($method) === 'post') {
if (($element === null && $methods === null) || ($methods !== null && in_array('post', $methods))) {
$element = $this->findPost($index);
}
if ($element === null && $method === null || strtolower($method) === 'file') {
if (($element === null && $methods === null) || ($methods !== null && in_array('file', $methods))) {
$element = $this->findFile($index);
}
return ($element === null) ? $default : $element;
return ($element !== null) ? $element : $defaultValue;
}
/**
* Get input element value matching index
*
* @param string $index
* @param string|null $default
* @param string|null $method
* @param string|null $defaultValue
* @param array|string|null $methods
* @return InputItem|string
*/
public function get($index, $default = null, $method = null)
public function get($index, $defaultValue = null, $methods = null)
{
$input = $this->getObject($index, $default, $method);
$input = $this->getObject($index, $defaultValue, $methods);
if ($input instanceof InputItem) {
return (trim($input->getValue()) === '') ? $default : $input->getValue();
return (trim($input->getValue()) === '') ? $defaultValue : $input->getValue();
}
return $input;
}
/**
* Check if a input-item exist
*
* @param string $index
* @return bool
*/
public function exists($index)
{
return ($this->getObject($index) !== null);
@@ -194,7 +264,7 @@ class Input
$contents = file_get_contents('php://input');
if (stripos(trim($contents), '{') === 0) {
if (strpos(trim($contents), '{') === 0) {
$output = json_decode($contents, true);
if ($output === false) {
$output = [];
@@ -206,11 +276,7 @@ class Input
if ($filter !== null) {
$output = array_filter($output, function ($key) use ($filter) {
if (in_array($key, $filter)) {
return true;
}
return false;
return (in_array($key, $filter) === true);
}, ARRAY_FILTER_USE_KEY);
}

View File

@@ -4,8 +4,8 @@ namespace Pecee\Http\Input;
class InputFile implements IInputItem
{
public $index;
public $value;
public $name;
public $filename;
public $size;
public $type;
public $error;
@@ -21,7 +21,9 @@ class InputFile implements IInputItem
/**
* Create from array
*
* @param array $values
* @throws \InvalidArgumentException
* @return static
*/
public static function createFromArray(array $values)
@@ -30,12 +32,22 @@ class InputFile implements IInputItem
throw new \InvalidArgumentException('Index key is required');
}
/* Easy way of ensuring that all indexes-are set and not filling the screen with isset() */
$values = array_merge([
'tmp_name' => null,
'type' => null,
'size' => null,
'name' => null,
'error' => null,
], $values);
$input = new static($values['index']);
$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);
$input->setError($values['error'])
->setSize($values['size'])
->setType($values['type'])
->setTmpName($values['tmp_name'])
->setFilename($values['name']);
return $input;
}
@@ -48,6 +60,11 @@ class InputFile implements IInputItem
return $this->index;
}
/**
* Set input index
* @param string $index
* @return static $this
*/
public function setIndex($index)
{
$this->index = $index;
@@ -75,6 +92,10 @@ class InputFile implements IInputItem
return $this;
}
/**
* Get mime-type of file
* @return string
*/
public function getMime()
{
return $this->getType();
@@ -100,12 +121,19 @@ class InputFile implements IInputItem
return $this;
}
/**
* Returns extension without "."
*
* @return string
*/
public function getExtension()
{
return pathinfo($this->getName(), PATHINFO_EXTENSION);
}
/**
* Get human friendly name
*
* @return string
*/
public function getName()
@@ -113,6 +141,13 @@ class InputFile implements IInputItem
return $this->name;
}
/**
* Set human friendly name.
* Useful for adding validation etc.
*
* @param string $name
* @return static $this
*/
public function setName($name)
{
$this->name = $name;
@@ -120,29 +155,63 @@ class InputFile implements IInputItem
return $this;
}
/**
* Set filename
*
* @param string $name
* @return static $this
*/
public function setFilename($name)
{
$this->filename = $name;
return $this;
}
/**
* Get filename
*
* @return string mixed
*/
public function getFilename()
{
return $this->filename;
}
/**
* Move the uploaded temporary file to it's new home
*
* @param string $destination
* @return bool
*/
public function move($destination)
{
return move_uploaded_file($this->tmpName, $destination);
}
/**
* Get file contents
*
* @return string
*/
public function getContents()
{
return file_get_contents($this->tmpName);
}
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Return true if an upload error occured.
*
* @return bool
*/
public function hasError()
{
return ($this->getError() !== 0);
}
/**
* Get upload-error code.
*
* @return string
*/
public function getError()
@@ -152,6 +221,7 @@ class InputFile implements IInputItem
/**
* Set error
*
* @param int $error
* @return static $this
*/
@@ -162,27 +232,6 @@ class InputFile implements IInputItem
return $this;
}
public function toArray()
{
return [
'tmp_name' => $this->tmpName,
'type' => $this->type,
'size' => $this->size,
'name' => $this->name,
'error' => $this->error,
];
}
public function __toString()
{
return $this->getValue();
}
public function getValue()
{
return $this->getTmpName();
}
/**
* @return string
*/
@@ -202,4 +251,21 @@ class InputFile implements IInputItem
return $this;
}
public function __toString()
{
return $this->getTmpName();
}
public function toArray()
{
return [
'tmp_name' => $this->tmpName,
'type' => $this->type,
'size' => $this->size,
'name' => $this->filename,
'error' => $this->error,
];
}
}

View File

@@ -75,4 +75,5 @@ class InputItem implements IInputItem
{
return (string)$this->value;
}
}

View File

@@ -58,7 +58,7 @@ class BaseCsrfVerifier implements IMiddleware
public function handle(Request $request, ILoadableRoute &$route = null)
{
if (in_array($request->getMethod(), ['post', 'put', 'delete']) === true && $this->skip($request) === false) {
if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete']) === true) {
$token = $request->getInput()->get(static::POST_KEY, null, 'post');
@@ -77,7 +77,7 @@ class BaseCsrfVerifier implements IMiddleware
public function generateToken()
{
$token = $this->csrfToken->generateToken();
$token = CsrfToken::generateToken();
$this->csrfToken->setToken($token);
return $token;
@@ -85,7 +85,7 @@ class BaseCsrfVerifier implements IMiddleware
public function hasToken()
{
if ($this->token != null) {
if ($this->token !== null) {
return true;
}

View File

@@ -15,10 +15,10 @@ class Request
public function __construct()
{
$this->parseHeaders();
$this->host = $this->getHeader('http-host');;
$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()
@@ -40,11 +40,7 @@ class Request
public function isSecure()
{
if ($this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443) {
return true;
}
return false;
return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443;
}
/**
@@ -108,7 +104,7 @@ class Request
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) {
return $this->getHeader('http-x-forwarded_for');
}
@@ -137,7 +133,7 @@ class Request
* Get header value by name
*
* @param string $name
* @param object|null $defaultValue
* @param string|null $defaultValue
*
* @return string|null
*/
@@ -217,6 +213,11 @@ class Request
$this->method = $method;
}
public function __isset($name)
{
return $this->data[$name] ?? null;
}
public function __set($name, $value = null)
{
$this->data[$name] = $value;
@@ -224,7 +225,7 @@ class Request
public function __get($name)
{
return isset($this->data[$name]) ? $this->data[$name] : null;
return $this->data[$name] ?? null;
}
}

View File

@@ -64,14 +64,14 @@ class Response
$this->headers([
'Cache-Control: public',
'Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT',
'Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT',
'Etag: ' . $eTag,
]);
$httpModified = $this->request->getHeader('http-if-modified-since');
$httpIfNoneMatch = $this->request->getHeader('http-if-none-match');
if ($httpModified !== null && strtotime($httpModified) == $lastModified || $httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) {
if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModified)) {
$this->header('HTTP/1.1 304 Not Modified');
@@ -111,9 +111,8 @@ class Response
*/
public function headers(array $headers)
{
$max = count($headers);
for ($i = 0; $i < $max; $i++) {
$this->header($headers[$i]);
foreach ($headers as $header) {
$this->header($header);
}
return $this;

View File

@@ -22,7 +22,7 @@ interface ILoadableRoute extends IRoute
* @param Request $request
* @param ILoadableRoute $route
*/
public function loadMiddleware(Request $request, ILoadableRoute &$route);
public function loadMiddleware(Request $request, ILoadableRoute $route);
public function getUrl();

View File

@@ -18,7 +18,7 @@ interface IRoute
* Returns class to be rendered.
*
* @param Request $request
* @return object
* @return \Closure|string
*/
public function renderRoute(Request $request);

View File

@@ -9,7 +9,14 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
{
const PARAMETERS_REGEX_MATCH = '%s([\w\-\_]*?)\%s{0,1}%s';
/**
* @var
*/
protected $url;
/**
* @var string
*/
protected $name;
/**
@@ -19,7 +26,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
* @param ILoadableRoute $route
* @throws HttpException
*/
public function loadMiddleware(Request $request, ILoadableRoute &$route)
public function loadMiddleware(Request $request, ILoadableRoute $route)
{
if (count($this->getMiddlewares()) > 0) {
@@ -114,7 +121,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
$param = $keys[$i];
$value = $params[$param];
$value = (isset($parameters[$param])) ? $parameters[$param] : $value;
$value = $parameters[$param] ?? $value;
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
$url = str_ireplace([sprintf($param1, $param), sprintf($param2, $param)], $value, $url);

View File

@@ -86,7 +86,7 @@ abstract class Route implements IRoute
if ($character === '{') {
/* Remove "/" and "\" from regex */
if (substr($regex, strlen($regex) - 1) === '/') {
$regex = substr($regex, 0, strlen($regex) - 2);
$regex = substr($regex, 0, -2);
}
$isParameter = true;
@@ -99,7 +99,7 @@ abstract class Route implements IRoute
}
if ($lastCharacter === '?') {
$parameter = substr($parameter, 0, strlen($parameter) - 1);
$parameter = substr($parameter, 0, -1);
$regex .= '(?:\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?)?';
$required = false;
} else {
@@ -136,13 +136,13 @@ abstract class Route implements IRoute
$name = $parameterNames[$i];
$parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null;
$parameterValue = $parameterValues[$name['name']] ?? null;
if ($name['required'] && $parameterValue === null) {
if ($parameterValue === null && $name['required']) {
throw new HttpException('Missing required parameter ' . $name['name'], 404);
}
if ($name['required'] === false && $parameterValue === null) {
if ($parameterValue === null && $name['required'] === false) {
continue;
}
@@ -384,10 +384,13 @@ abstract class Route implements IRoute
}
if (count($this->parameters) > 0) {
/* Ensure the right order + values */
$parameters = ($values['parameters'] + $this->parameters);
$parameters = ($values['parameters'] ?? []) + $this->parameters;
$parameters = array_merge($parameters, $this->parameters);
$this->setParameters($parameters);
$values['parameters'] = $parameters;
}
if (count($this->middlewares) > 0) {
@@ -406,7 +409,7 @@ abstract class Route implements IRoute
*/
public function setSettings(array $values, $merge = false)
{
if (isset($values['namespace']) && $this->namespace === null) {
if ($this->namespace === null && isset($values['namespace'])) {
$this->setNamespace($values['namespace']);
}

View File

@@ -31,11 +31,11 @@ class RouteController extends LoadableRoute implements IControllerRoute
}
/* Remove method/type */
if (stripos($name, '.') !== false) {
if (strpos($name, '.') !== false) {
$method = substr($name, strrpos($name, '.') + 1);
$newName = substr($name, 0, strrpos($name, '.'));
if (strtolower($this->name) === strtolower($newName) && in_array($method, $this->names)) {
if (in_array($method, $this->names) === true && strtolower($this->name) === strtolower($newName)) {
return true;
}
}
@@ -43,10 +43,15 @@ class RouteController extends LoadableRoute implements IControllerRoute
return parent::hasName($name);
}
/**
* @param string|null $method
* @param string|array|null $parameters
* @param string|null $name
* @return string
*/
public function findUrl($method = null, $parameters = null, $name = null)
{
if (stripos($name, '.') !== false) {
if (strpos($name, '.') !== false) {
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names);
if ($found !== false) {
$method = $found;
@@ -54,7 +59,6 @@ class RouteController extends LoadableRoute implements IControllerRoute
}
$url = '';
$parameters = (array)$parameters;
/* Remove requestType from method-name, if it exists */
@@ -115,7 +119,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$url = parse_url(urldecode($request->getUri()), PHP_URL_PATH);
$url = rtrim($url, '/') . '/';
if (strtolower($url) == strtolower($this->url) || stripos($url, $this->url) === 0) {
if (stripos($url, $this->url) === 0 && strtolower($url) === strtolower($this->url)) {
$strippedUrl = trim(str_ireplace($this->url, '/', $url), '/');
@@ -127,6 +131,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$this->method = $method;
array_shift($path);
$this->parameters = $path;
// Set callback

View File

@@ -27,8 +27,8 @@ class RouteGroup extends Route implements IGroupRoute
$domain = $this->domains[$i];
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
if ($parameters !== null) {
$this->parameters = $parameters;
if ($parameters !== null && count($parameters) > 0) {
$this->parameters = array_merge($this->parameters, $parameters);
return true;
}

View File

@@ -15,6 +15,17 @@ class RouteResource extends LoadableRoute implements IControllerRoute
'update' => '',
'destroy' => '',
];
protected $methodNames = [
'index' => 'index',
'create' => 'create',
'store' => 'store',
'show' => 'show',
'edit' => 'edit',
'update' => 'update',
'destroy' => 'destroy',
];
protected $names = [];
protected $controller;
@@ -42,7 +53,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
}
/* Remove method/type */
if (stripos($name, '.') !== false) {
if (strpos($name, '.') !== false) {
$name = substr($name, 0, strrpos($name, '.'));
}
@@ -51,7 +62,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
public function findUrl($method = null, $parameters = null, $name = null)
{
$method = array_search($name, $this->names);
$method = array_search($name, $this->names, false);
if ($method !== false) {
return rtrim($this->url . $this->urls[$method], '/') . '/';
}
@@ -104,43 +115,43 @@ class RouteResource extends LoadableRoute implements IControllerRoute
$parameters = array_merge($this->parameters, (array)$parameters);
$action = isset($parameters['action']) ? $parameters['action'] : null;
$action = $parameters['action'] ?? null;
unset($parameters['action']);
$method = $request->getMethod();
// Delete
if (isset($parameters['id']) && $method === static::REQUEST_TYPE_DELETE) {
return $this->call('destroy', $parameters);
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('update', $parameters);
return $this->call($this->methodNames['update'], $parameters);
}
// Edit
if (isset($parameters['id']) && strtolower($action) === 'edit' && $method === static::REQUEST_TYPE_GET) {
return $this->call('edit', $parameters);
if ($method === static::REQUEST_TYPE_GET && isset($parameters['id']) && strtolower($action) === 'edit') {
return $this->call($this->methodNames['edit'], $parameters);
}
// Create
if (strtolower($action) === 'create' && $method === static::REQUEST_TYPE_GET) {
return $this->call('create', $parameters);
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('store', $parameters);
return $this->call($this->methodNames['store'], $parameters);
}
// Show
if (isset($parameters['id']) && $method === static::REQUEST_TYPE_GET) {
return $this->call('show', $parameters);
if ($method === static::REQUEST_TYPE_GET && isset($parameters['id'])) {
return $this->call($this->methodNames['show'], $parameters);
}
// Index
return $this->call('index', $parameters);
return $this->call($this->methodNames['index'], $parameters);
}
return null;
@@ -182,6 +193,29 @@ class RouteResource extends LoadableRoute implements IControllerRoute
return $this;
}
/**
* Define custom method name for resource controller
*
* @param array $names
* @return static $this
*/
public function setMethodNames(array $names)
{
$this->methodNames = $names;
return $this;
}
/**
* Get method names
*
* @return array $this
*/
public function getMethodNames()
{
return $this->methodNames;
}
/**
* Merge with information from another route.
*
@@ -195,6 +229,10 @@ class RouteResource extends LoadableRoute implements IControllerRoute
$this->names = $values['names'];
}
if (isset($values['methods'])) {
$this->methodNames = $values['methods'];
}
parent::setSettings($values, $merge);
return $this;

View File

@@ -100,7 +100,7 @@ class Router
return static::$instance;
}
public function __construct()
protected function __construct()
{
$this->reset();
}
@@ -137,16 +137,26 @@ class Router
return $route;
}
/**
* Process added routes.
*
* @param array $routes
* @param IGroupRoute|null $group
* @param IRoute|null $parent
*/
protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null)
{
// Loop through each route-request
$max = count($routes) - 1;
$exceptionHandlers = [];
/* @var $route IRoute */
for ($i = $max; $i >= 0; $i--) {
$route = $routes[$i];
/* @var $route IGroupRoute */
if ($route instanceof IGroupRoute) {
$group = $route;
@@ -159,9 +169,9 @@ class Router
if ($route->matchRoute($this->request)) {
/* Add exceptionhandlers */
/* Add exception handlers */
if (count($route->getExceptionHandlers()) > 0) {
$this->exceptionHandlers = array_merge($route->getExceptionHandlers(), $this->exceptionHandlers);
$exceptionHandlers += $route->getExceptionHandlers();
}
}
@@ -172,7 +182,6 @@ class Router
/* Add the parent group */
$route->setGroup($group);
}
if ($parent !== null) {
@@ -201,6 +210,8 @@ class Router
$this->processRoutes($stack, $route, $group);
}
}
$this->exceptionHandlers = array_unique(array_merge($exceptionHandlers, $this->exceptionHandlers));
}
public function routeRequest($rewrite = false)
@@ -253,7 +264,7 @@ class Router
if ($route->matchRoute($this->request)) {
/* Check if request method matches */
if (count($route->getRequestMethods()) > 0 && !in_array($this->request->getMethod(), $route->getRequestMethods())) {
if (count($route->getRequestMethods()) > 0 && in_array($this->request->getMethod(), $route->getRequestMethods()) === false) {
$routeNotAllowed = true;
continue;
}
@@ -262,7 +273,7 @@ class Router
$this->loadedRoute->loadMiddleware($this->request, $this->loadedRoute);
/* If the request has changed, we reinitialize the router */
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) === false) {
$this->routeRewrites[] = $this->request->getUri();
$this->routeRequest(true);
@@ -309,7 +320,7 @@ class Router
$request = $handler->handleError($this->request, $this->loadedRoute, $e);
/* If the request has changed */
if ($request !== null && $this->request->getUri() !== $this->originalUrl && !in_array($request->getUri(), $this->routeRewrites)) {
if ($request !== null && $this->request->getUri() !== $this->originalUrl && in_array($request->getUri(), $this->routeRewrites) === false) {
$this->request = $request;
$this->routeRewrites[] = $request->getUri();
$this->routeRequest(true);
@@ -375,7 +386,7 @@ class Router
if (strpos($name, '@') !== false && strpos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) {
/* Check if the entire callback is matching */
if (strtolower($route->getCallback()) === strtolower($name) || strpos($route->getCallback(), $name) === 0) {
if (strpos($route->getCallback(), $name) === 0 || strtolower($route->getCallback()) === strtolower($name)) {
return $route;
}
@@ -404,6 +415,7 @@ class Router
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @throws \InvalidArgumentException
* @return string
*/
public function getUrl($name = null, $parameters = null, $getParams = null)
@@ -439,7 +451,7 @@ class Router
}
/* Using @ is most definitely a controller@method or alias@method */
if (stripos($name, '@') !== false) {
if (strpos($name, '@') !== false) {
list($controller, $method) = explode('@', $name);
/* Loop through all the routes to see if we can find a match */

View File

@@ -309,6 +309,7 @@ class SimpleRouter
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @throws \Exception
* @return string
*/
public static function getUrl($name = null, $parameters = null, $getParams = null)