Compare commits

..

51 Commits

Author SHA1 Message Date
Simon Sessingø 496d3e7182 Merge pull request #315 from skipperbent/v3-development
Version 3.4.5.5
2017-11-25 01:34:53 +01:00
Simon Sessingø f2819f866e Merge pull request #314 from skipperbent/v3-documentation-spelling
Fixed spelling in documentation
2017-11-25 01:34:01 +01:00
Simon Sessingø b9aa348b38 Merge branch 'v3-development' of github.com:skipperbent/simple-php-router into v3-development 2017-11-25 01:32:24 +01:00
Simon Sessingø c29c52ae16 Fixed default-namespace causing router to break on closures. 2017-11-25 01:31:43 +01:00
Simon Sessingo 6547c07113 Fixed spelling in documentation 2017-11-20 21:53:41 +01:00
Simon Sessingø 1fd13ed2aa Merge pull request #311 from skipperbent/v3-development
V3 development
2017-11-10 13:02:49 +01:00
Simon Sessingø fde77969c0 Merge pull request #310 from skipperbent/v3-csrftoken-update
Csrf-token are now refreshed on each page-load to avoid timeout.
2017-11-10 13:02:23 +01:00
Simon Sessingø c3072e8886 Csrf-token are now refreshed on each page-load to avoid timeout. 2017-11-10 12:59:59 +01:00
Simon Sessingø 9d5c4a2ed1 Merge pull request #308 from skipperbent/v3-development
3.4.5.4
2017-11-10 08:24:55 +01:00
Simon Sessingø 97753f5370 Minor optimisations. 2017-11-10 08:23:15 +01:00
Simon Sessingø b8634bcf79 Merge pull request #307 from skipperbent/revert-306-revert-305-v3-development
Revert "Revert "V3 development""
2017-11-08 04:11:50 +01:00
Simon Sessingø 6ad22a3816 Revert "Revert "V3 development"" 2017-11-08 04:11:40 +01:00
Simon Sessingø ed41cd55af Merge pull request #306 from skipperbent/revert-305-v3-development
Revert "V3 development"
2017-11-08 04:09:55 +01:00
Simon Sessingø ebeca952cf Revert "V3 development" 2017-11-08 04:09:41 +01:00
Simon Sessingø 0672e85fd7 Merge pull request #305 from skipperbent/v3-development
V3 development
2017-11-08 04:09:31 +01:00
Simon Sessingø 927f8d7b3c Merge pull request #304 from jatubio/patch-3
Documentation: Add IIS Trooubleshooting section.
2017-11-08 04:09:14 +01:00
Juan Antonio Tubio 74177a2082 Update README.md 2017-11-04 00:59:52 +01:00
Juan Antonio Tubio 2221bced4f Update README.md 2017-11-04 00:27:13 +01:00
Juan Antonio Tubio 6559278511 Documentation: Add file exception rules samples to IIS web.config 2017-11-04 00:19:51 +01:00
Simon Sessingø 8b9698229d Merge pull request #302 from skipperbent/v3
V3
2017-10-23 22:08:23 +02:00
Simon Sessingø a565f66c4c Merge pull request #301 from skipperbent/v3-development
Version 3.4.5.3
2017-10-23 22:08:09 +02:00
Simon Sessingø 832ef992a3 Merge pull request #300 from skipperbent/csrf-documentation
Added CSRF form-example in documentation (issue: #299)
2017-10-23 22:05:41 +02:00
Simon Sessingø cc5e417db9 Update README.md 2017-10-23 22:05:27 +02:00
Simon Sessingø 2cc90e28d0 Update README.md 2017-10-23 22:04:28 +02:00
Simon Sessingø eb63a5d6ba Added CSRF form-example in documentation (issue: #299) 2017-10-23 22:01:19 +02:00
Simon Sessingø a07b30a80d Merge pull request #298 from jatubio/patch-2
Added more info on route or method not allowed exception
2017-10-12 15:53:03 +02:00
Juan Antonio Tubio c45cd6347a Added more info on route or method not allowed exception 2017-10-11 16:02:26 +02:00
Simon Sessingø 4a353efc97 Merge pull request #296 from skipperbent/v3
V3
2017-10-07 17:53:27 +02:00
Simon Sessingø f7ce440c56 Merge pull request #295 from skipperbent/v3-development
Fixed: try next exception-handler if one throws error.
2017-10-07 17:53:17 +02:00
Simon Sessingø 41705f030a Fixed: try next exception-handler if one throws error. 2017-10-07 12:33:24 +01:00
Simon Sessingø 18fa0f9610 Merge pull request #294 from skipperbent/v3
V3
2017-09-25 08:51:13 +02:00
Simon Sessingø 66ecf0ee33 Merge pull request #293 from skipperbent/v3-development
Readded csrf_token helper function - don't run away this time.
2017-09-25 08:51:02 +02:00
Simon Sessingø 4ba15033d9 Readded csrf_token helper function - don't run away this time. 2017-09-09 01:40:44 +01:00
Simon Sessingø 60393a3722 Merge pull request #291 from skipperbent/v3
V3
2017-09-03 19:43:22 +02:00
Simon Sessingø cfa18e520a Merge pull request #290 from skipperbent/v3-development
Version 3.4.5
2017-09-03 19:43:09 +02:00
Simon Sessingø 5e448f0835 Merge pull request #289 from skipperbent/v3-group-parameters
V3 partial group support
2017-09-03 19:37:51 +02:00
Simon Sessingø 98ad310404 Updated documentation. 2017-09-03 18:36:41 +01:00
Simon Sessingø a5aac57ce9 Added RoutePartialGroup support. 2017-09-03 18:24:51 +01:00
Simon Sessingø 7f924c7d0a Added RouterGroupTest unit-tests. 2017-09-03 16:49:15 +01:00
Simon Sessingø 3a90578351 Added parameter support for Group routes. 2017-09-03 16:37:20 +01:00
Simon Sessingø 52e0f5ef94 Removed link from documentation that has been moved. 2017-09-01 18:01:56 +01:00
Simon Sessingø 3df3ef36ef Merge pull request #288 from skipperbent/v3
V3
2017-08-31 13:05:45 +02:00
Simon Sessingø 0090c167bb Merge pull request #287 from skipperbent/v3-development
Response->json now accepts either array or \JsonSerializable (issue: #284)
2017-08-31 13:05:14 +02:00
Simon Sessingø ae68598024 Response->json now accepts either array or \JsonSerializable (issue: 2017-08-31 12:03:17 +01:00
Simon Sessingø c723ca7e61 Merge pull request #283 from skipperbent/v3
V3
2017-08-24 16:53:29 +02:00
Simon Sessingø 7362b748af Merge pull request #282 from skipperbent/v3-development
V3 development
2017-08-24 16:53:20 +02:00
Simon Sessingø 4fe85d6568 Merge pull request #281 from skipperbent/v3-fix-urldecode
Urldecode is now used on all urls in Uri class (issue: #268)
2017-08-24 16:53:04 +02:00
Simon Sessingø c82d91375c Urldecode is now used on all urls in Uri class (issue: #268) 2017-08-24 15:50:13 +01:00
Simon Sessingø e3b6899375 Merge pull request #280 from skipperbent/v3
V3
2017-08-24 03:13:06 +02:00
Simon Sessingø a179450018 Merge pull request #277 from skipperbent/v3
V3
2017-08-23 23:50:26 +02:00
Simon Sessingø ac3e9ed2ac Merge pull request #274 from skipperbent/v3
V3
2017-08-23 22:31:00 +02:00
15 changed files with 295 additions and 94 deletions
+78 -9
View File
@@ -43,6 +43,7 @@ If you want a great new feature or experience any issues what-so-ever, please fe
- [Namespaces](#namespaces)
- [Subdomain-routing](#subdomain-routing)
- [Route prefixes](#route-prefixes)
- [Partial groups](#partial-groups)
- [Form Method Spoofing](#form-method-spoofing)
- [Accessing The Current Route](#accessing-the-current-route)
- [Other examples](#other-examples)
@@ -79,7 +80,6 @@ If you want a great new feature or experience any issues what-so-ever, please fe
- [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically)
- [Adding routes manually](#adding-routes-manually)
- [Parameters](#parameters)
- [Custom default regex for matching parameters](#custom-default-regex-for-matching-parameters)
- [Extending](#extending)
- [Credits](#credits)
@@ -212,6 +212,24 @@ Simply create a new `web.config` file in your projects `public` directory and pa
</configuration>
```
#### Troubleshooting
If you do not have a `favicon.ico` file in your project, you can get a `NotFoundHttpException` (404 - not found).
To add `favicon.ico` to the IIS ignore-list, add the following line to the `<conditions>` group:
```
<add input="{REQUEST_FILENAME}" negate="true" pattern="favicon.ico" ignoreCase="true" />
```
You can also make one exception for files with some extensions:
```
<add input="{REQUEST_FILENAME}" pattern="\.ico|\.png|\.css|\.jpg" negate="true" ignoreCase="true" />
```
If you are using `$_SERVER['ORIG_PATH_INFO']`, you will get `\index.php\` as part of the returned value. For example:
```
/index.php/test/mypage.php
```
### Configuration
Create a new file, name it `routes.php` and place it in your library folder. This will be the file where you define all the routes for your project.
@@ -249,7 +267,8 @@ We recommend that you add these helper functions to your project. These will all
To implement the functions below, simply copy the code to a new file and require the file before initializing the router or copy the `helpers.php` we've included in this library.
```php
<?php
use Pecee\SimpleRouter\SimpleRouter as Router;
/**
* Get url for a route by using either name/alias, class or method name.
*
@@ -269,7 +288,7 @@ To implement the functions below, simply copy the code to a new file and require
*/
function url($name = null, $parameters = null, $getParams = null)
{
return SimpleRouter::getUrl($name, $parameters, $getParams);
return Router::getUrl($name, $parameters, $getParams);
}
/**
@@ -277,7 +296,7 @@ function url($name = null, $parameters = null, $getParams = null)
*/
function response()
{
return SimpleRouter::response();
return Router::response();
}
/**
@@ -285,7 +304,7 @@ function response()
*/
function request()
{
return SimpleRouter::request();
return Router::request();
}
/**
@@ -297,8 +316,7 @@ function request()
*/
function input($index = null, $defaultValue = null, $methods = null)
{
if($index !== null)
{
if ($index !== null) {
return request()->getInput()->get($index, $defaultValue, $methods);
}
@@ -313,6 +331,20 @@ function redirect($url, $code = null)
response()->redirect($url);
}
/**
* Get current csrf-token
* @return string|null
*/
function csrf_token()
{
$baseVerifier = Router::router()->getCsrfVerifier();
if ($baseVerifier !== null) {
return $baseVerifier->getToken();
}
return null;
}
```
---
@@ -358,7 +390,7 @@ SimpleRouter::any('foo', function() {
});
```
We've created a simple method which matches `GET` and `POST` which is most commenly used:
We've created a simple method which matches `GET` and `POST` which is most commonly used:
```php
SimpleRouter::form('foo', function() {
@@ -542,7 +574,7 @@ SimpleRouter::group(['namespace' => 'Admin'], function () {
});
```
### Subdomain-routing
### Sub domain-routing
Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array:
@@ -566,6 +598,29 @@ SimpleRouter::group(['prefix' => '/admin'], function () {
});
```
## Partial groups
Partial router groups has the same benefits as a normal group, but supports parameters and are only rendered once the url has matched.
This can be extremely useful in situations, where you only want special routes to be added, when a certain criteria or logic has been met.
**NOTE:** Use partial groups with caution as routes added within are only rendered and available once the url of the partial-group has matched. This can cause `url()` not to find urls for the routes added within.
**Example:**
```php
SimpleRouter::partialGroup('/admin/{applicationId}', function ($applicationId) {
SimpleRouter::get('/', function($applicationId) {
// Matches The "/admin/applicationId" URL
});
});
```
## Form Method Spoofing
HTML forms do not support `PUT`, `PATCH` or `DELETE` actions. So, when defining `PUT`, `PATCH` or `DELETE` routes that are called from an HTML form, you will need to add a hidden `_method` field to the form. The value sent with the `_method` field will be used as the HTTP request method:
@@ -672,6 +727,20 @@ You can get the CSRF-token by calling the helper method:
csrf_token();
```
The default name/key for the input-field is `csrf_token` and is defined in the `POST_KEY` constant in the `BaseCsrfVerifier` class.
You can change the key by overwriting the constant in your own CSRF-verifier class.
**Example:**
The example below will post to the current url with a hidden field "`csrf_token`".
```html
<form method="post" action="<?= url(); ?>">
<input type="hidden" name="csrf_token" value="<?= csrf_token(); ?>">
<!-- other input elements here -->
</form>
```
---
# Middlewares
+14
View File
@@ -63,4 +63,18 @@ function redirect($url, $code = null)
}
response()->redirect($url);
}
/**
* Get current csrf-token
* @return string|null
*/
function csrf_token()
{
$baseVerifier = Router::router()->getCsrfVerifier();
if ($baseVerifier !== null) {
return $baseVerifier->getToken();
}
return null;
}
+19 -7
View File
@@ -1,4 +1,5 @@
<?php
namespace Pecee;
class CsrfToken
@@ -15,7 +16,7 @@ class CsrfToken
*/
public static function generateToken()
{
if (function_exists('random_bytes')) {
if (function_exists('random_bytes') === true) {
return bin2hex(random_bytes(32));
}
@@ -46,25 +47,36 @@ class CsrfToken
/**
* Set csrf token cookie
* Overwrite this method to save the token to another storage like session etc.
*
* @param $token
* @param string $token
*/
public function setToken($token)
{
$this->token = $token;
setcookie(static::CSRF_KEY, $token, time() + 60 * 120, '/');
}
/**
* Get csrf token
* @param string|null $defaultValue
* @return string|null
*/
public function getToken()
public function getToken($defaultValue = null)
{
if ($this->hasToken() === true) {
return $_COOKIE[static::CSRF_KEY];
}
$this->token = ($this->hasToken() === true) ? $_COOKIE[static::CSRF_KEY] : null;
return null;
return ($this->token !== null) ? $this->token : $defaultValue;
}
/**
* Refresh existing token
*/
public function refresh()
{
if ($this->token !== null) {
$this->setToken($this->token);
}
}
/**
@@ -1,4 +1,5 @@
<?php
namespace Pecee\Http\Middleware;
use Pecee\CsrfToken;
@@ -19,7 +20,7 @@ class BaseCsrfVerifier implements IMiddleware
$this->csrfToken = new CsrfToken();
// Generate or get the CSRF-Token from Cookie.
$this->token = ($this->hasToken() === false) ? $this->generateToken() : $this->csrfToken->getToken();
$this->token = $this->csrfToken->getToken($this->generateToken());
}
/**
@@ -72,6 +73,9 @@ class BaseCsrfVerifier implements IMiddleware
}
// Refresh existing token
$this->csrfToken->refresh();
}
public function generateToken()
+3 -25
View File
@@ -1,4 +1,5 @@
<?php
namespace Pecee\Http;
use Pecee\Http\Input\Input;
@@ -42,13 +43,7 @@ class Request
{
$this->headers = [];
$max = count($_SERVER) - 1;
$keys = array_keys($_SERVER);
for ($i = $max; $i >= 0; $i--) {
$key = $keys[$i];
$value = $_SERVER[$key];
foreach ($_SERVER as $key => $value) {
$this->headers[strtolower($key)] = $value;
$this->headers[strtolower(str_replace('_', '-', $key))] = $value;
}
@@ -167,24 +162,7 @@ class Request
*/
public function getHeader($name, $defaultValue = null)
{
if (array_key_exists(strtolower($name), $this->headers) === true) {
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;
return isset($this->headers[strtolower($name)]) ? $this->headers[strtolower($name)] : $defaultValue;
}
/**
+11 -5
View File
@@ -1,4 +1,5 @@
<?php
namespace Pecee\Http;
class Response
@@ -82,14 +83,19 @@ class Response
}
/**
* Json encode array
* @param array $value
* Json encode
* @param array|\JsonSerializable $value
* @throws \InvalidArgumentException;
*/
public function json(array $value)
public function json($value)
{
$this->header('Content-Type: application/json');
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');
echo json_encode($value);
die();
exit(0);
}
/**
+1 -1
View File
@@ -19,7 +19,7 @@ class Uri
public function __construct($url)
{
$this->originalUrl = $url;
$this->data = array_merge($this->data, $this->parseUrl($url));
$this->data = array_merge($this->data, $this->parseUrl(urldecode($url)));
if (isset($this->data['path']) === true && $this->data['path'] !== '/') {
$this->data['path'] = rtrim($this->data['path'], '/') . '/';
@@ -0,0 +1,8 @@
<?php
namespace Pecee\SimpleRouter\Route;
interface IPartialGroupRoute
{
}
+1 -1
View File
@@ -21,7 +21,7 @@ interface IRoute
*
* @param Request $request
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
* @return void
* @return string
*/
public function renderRoute(Request $request);
+4 -3
View File
@@ -42,6 +42,7 @@ abstract class Route implements IRoute
protected $defaultParameterRegex;
protected $paramModifiers = '{}';
protected $paramOptionalSymbol = '?';
protected $urlRegex = '/^%s\/?$/u';
protected $group;
protected $parent;
protected $callback;
@@ -69,7 +70,7 @@ abstract class Route implements IRoute
$callback = $this->getCallback();
if ($callback === null) {
return;
return null;
}
/* Render callback function */
@@ -154,14 +155,14 @@ abstract class Route implements IRoute
$urlRegex = preg_quote($route, '/');
}
if (preg_match('/^' . $urlRegex . '\/?$/u', $url, $matches) > 0) {
if (preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) > 0) {
$values = [];
if (isset($parameters[1]) === true) {
/* Only take matched parameters with name */
foreach ($parameters[1] as $name) {
foreach ((array)$parameters[1] as $name) {
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
}
}
+2 -2
View File
@@ -150,11 +150,11 @@ class RouteGroup extends Route implements IGroupRoute
$this->setPrefix($values['prefix'] . $this->prefix);
}
if (isset($values['exceptionHandler'])) {
if ($merge === false && isset($values['exceptionHandler'])) {
$this->setExceptionHandlers((array)$values['exceptionHandler']);
}
if (isset($values['domain'])) {
if ($merge === false && isset($values['domain'])) {
$this->setDomains((array)$values['domain']);
}
@@ -0,0 +1,36 @@
<?php
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute
{
protected $urlRegex = '/^%s\/?/u';
/**
* Method called to check if route matches
*
* @param string $url
* @param Request $request
* @return bool
*/
public function matchRoute($url, Request $request)
{
if ($this->prefix !== null) {
/* Parse parameters from current route */
$parameters = $this->parseParameters($this->prefix, $url);
/* If no custom regular expression or parameters was found on this route, we stop */
if ($parameters === null) {
return false;
}
/* Set the parameters */
$this->setParameters((array)$parameters);
}
return $this->matchDomain($request);
}
}
+55 -39
View File
@@ -10,6 +10,7 @@ use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Route\IControllerRoute;
use Pecee\SimpleRouter\Route\IGroupRoute;
use Pecee\SimpleRouter\Route\ILoadableRoute;
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
use Pecee\SimpleRouter\Route\IRoute;
class Router
@@ -129,15 +130,27 @@ class Router
$route = $routes[$i];
if ($parent !== null) {
/* Add the parent route */
$route->setParent($parent);
/* Add/merge parent settings with child */
$route->setSettings($parent->toArray(), true);
}
if ($group !== null) {
/* Add the parent group */
$route->setGroup($group);
}
/* @var $route IGroupRoute */
if ($route instanceof IGroupRoute) {
$group = $route;
$this->processingRoute = true;
$route->renderRoute($this->request);
$this->processingRoute = false;
if ($route->matchRoute($url, $this->request) === true) {
/* Add exception handlers */
@@ -146,23 +159,20 @@ class Router
$exceptionHandlers += $route->getExceptionHandlers();
}
/* Only render partial group if it matches */
if ($route instanceof IPartialGroupRoute) {
$this->processingRoute = true;
$route->renderRoute($this->request);
$this->processingRoute = false;
}
}
}
if ($group !== null) {
/* Add the parent group */
$route->setGroup($group);
}
if ($parent !== null) {
/* Add the parent route */
$route->setParent($parent);
/* Add/merge parent settings with child */
$route->setSettings($parent->toArray(), true);
if (($route instanceof IPartialGroupRoute) === false) {
$this->processingRoute = true;
$route->renderRoute($this->request);
$this->processingRoute = false;
}
}
if ($route instanceof ILoadableRoute) {
@@ -258,9 +268,8 @@ class Router
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
unset($this->processedRoutes[$i]);
$this->processedRoutes = array_values($this->processedRoutes);
$this->routeRequest(true);
return;
return $this->routeRequest(true);
}
/* Render route */
@@ -268,8 +277,6 @@ class Router
$this->request->setLoadedRoute($route);
return $route->renderRoute($this->request);
break;
}
}
@@ -278,7 +285,8 @@ class Router
}
if ($routeNotAllowed === true) {
$this->handleException(new HttpException('Route or method not allowed', 403));
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUri()->getPath(), $this->request->getMethod());
$this->handleException(new HttpException($message, 403));
}
if ($this->request->getLoadedRoute() === null) {
@@ -293,12 +301,15 @@ class Router
$this->handleException(new NotFoundHttpException($message, 404));
}
return null;
}
/**
* @param \Exception $e
* @throws HttpException
* @throws \Exception
* @return string
*/
protected function handleException(\Exception $e)
{
@@ -319,26 +330,31 @@ class Router
throw new HttpException('Exception handler must implement the IExceptionHandler interface.', 500);
}
if ($handler->handleError($this->request, $e) !== null) {
try {
$rewriteRoute = $this->request->getRewriteRoute();
if ($handler->handleError($this->request, $e) !== null) {
if ($rewriteRoute !== null) {
$rewriteRoute->loadMiddleware($this->request);
$rewriteRoute = $this->request->getRewriteRoute();
return $rewriteRoute->renderRoute($this->request);
if ($rewriteRoute !== null) {
$rewriteRoute->loadMiddleware($this->request);
return $rewriteRoute->renderRoute($this->request);
}
$rewriteUrl = $this->request->getRewriteUrl();
/* If the request has changed */
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
unset($this->exceptionHandlers[$i]);
$this->exceptionHandlers = array_values($this->exceptionHandlers);
return $this->routeRequest(true);
}
}
$rewriteUrl = $this->request->getRewriteUrl();
} catch (\Exception $e) {
/* If the request has changed */
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
unset($this->exceptionHandlers[$i]);
$this->exceptionHandlers = array_values($this->exceptionHandlers);
$this->routeRequest(true);
return;
}
}
}
@@ -579,4 +595,4 @@ class Router
return $this;
}
}
}
+29 -1
View File
@@ -16,6 +16,7 @@ use Pecee\Http\Response;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Route\IRoute;
use Pecee\SimpleRouter\Route\RoutePartialGroup;
use Pecee\SimpleRouter\Route\RouteController;
use Pecee\SimpleRouter\Route\RouteGroup;
use Pecee\SimpleRouter\Route\RouteResource;
@@ -171,14 +172,41 @@ class SimpleRouter
*/
public static function group(array $settings = [], \Closure $callback)
{
if (is_callable($callback) === false) {
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
$group = new RouteGroup();
$group->setCallback($callback);
$group->setSettings($settings);
static::router()->addRoute($group);
return $group;
}
/**
* Special group that has the same benefits as group but supports
* parameters and which are only rendered when the url matches.
*
* @param string $url
* @param array $settings
* @param \Closure $callback
* @throws \InvalidArgumentException
* @return RoutePartialGroup
*/
public static function partialGroup($url, \Closure $callback, array $settings = [])
{
if (is_callable($callback) === false) {
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
$settings['prefix'] = $url;
$group = new RoutePartialGroup();
$group->setSettings($settings);
$group->setCallback($callback);
static::router()->addRoute($group);
return $group;
@@ -399,7 +427,7 @@ class SimpleRouter
$callback = $route->getCallback();
/* Only add default namespace on relative callbacks */
if ($callback === null || $callback[0] !== '\\') {
if ($callback === null || (is_string($callback) === true && $callback[0] !== '\\')) {
$namespace = static::$defaultNamespace;
+29
View File
@@ -0,0 +1,29 @@
<?php
require_once 'Dummy/DummyMiddleware.php';
require_once 'Dummy/DummyController.php';
require_once 'Dummy/Handler/ExceptionHandler.php';
require_once 'Helpers/TestRouter.php';
class RouterPartialGroupTest extends PHPUnit_Framework_TestCase
{
public function testParameters()
{
$result1 = null;
$result2 = null;
TestRouter::partialGroup('{param1}/{param2}', function ($param1 = null, $param2 = null) use (&$result1, &$result2) {
$result1 = $param1;
$result2 = $param2;
TestRouter::get('/', 'DummyController@method1');
});
TestRouter::debug('/param1/param2', 'get');
$this->assertEquals('param1', $result1);
$this->assertEquals('param2', $result2);
}
}