Compare commits

..
10 Commits
6 changed files with 470 additions and 153 deletions
+191 -2
View File
@@ -1,3 +1,192 @@
# Routes # InforRoutes
https://stackoverflow.com/questions/8054165/using-put-method-in-html-form A simple and dependency free routing system providing:
- Non blocking dispatch of system `WEB` and `CLI` functionalities
- Parameters detection on the URL segments
- Route grouping based on namespaces
- Error handling and 404 detection
- Attachable and global middlewares
## Usage
### Installation
First install the package with `composer require inforsistemas/routes`. You might need to add a custom repository on the composer.json
```
"repositories": [{
"type": "composer",
"url": "https://satis.domain.com"
}],
```
### Server configuration
#### Requirements
The following packages need to be installed for the project to run
* Apache
- apache2 phpX.X phpX.X-fpm libapache2-mod-phpX.X
* Nginx
- nginx phpX.X phpX.X-fpm
The ports `80` and `443` must be open: `ufw allow 80 && ufw allow 443`
#### Apache
For apache, the basic required configuration
```
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public
ServerName example.com
<Directory /var/www >
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```
For a server with HTTPs, the configuration with redirection
```
<VirtualHost *:80>
ServerName example.com
Redirect / https://example.com
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public
ServerName urfat.com.br
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/example.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com.br/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
```
#### Nginx
*For Nginx,this is the basic required configuration with PHP-FPM*
```
server {
listen 82 default_server;
listen [::]:82 default_server;
server_name example.com;
root /var/www/html/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name localhost;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
#Check fpm-version
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
```
For a server with HTTPs, the configuration with redirection
```
server {
listen 80;
listen [::]:80;
listen 443 default_server ssl;
server_name example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS:!AES256";
ssl_prefer_server_ciphers on;
ssl_dhparam /path/to/my/dhp-4096.pem #sudo openssl dhparam -out /path/to/my/dhp-4096.pem 4096
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
```
#### Hello World
With the dependencies and the server with the correct configuration, create a index.php with the content
```
<?php
include_once 'vendor/autoload.php';
use Routes\RouteCollection as RouteCollection;
RouteCollection::get ("/", function(){
echo "Hello World";
});
RouteCollection::getInstance()->submit();
```
## Inner workings
The package consist in 3 main files, with `RouteCollection.php` providing the main API
- `Route.php` => Stores each route information
- `RouteCollection.php` => Aggregate all routes and provide a interface to interact with the routes dataset
- `RouteGroup.php` => Aggregate a group of routes based on their namespaces
The class `RouteCollection` is treated as a Singleton that return it's own global instance when loaded. The main interface would be something like: `RouteCollection::add($verb, $uri, $callback, $weight = 0)`, this method will return the instance of the `Route` object, so that the Route properties can be configured
*Route settings:*
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->doBlock()`
- After this route execute, no more routes would be executed
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->notBlock()`
- The execution of this route will not block the execution of the next routes
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->doIgnore()`
- This route will not count as a executed route, so a 404 can be detected
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareIgnore($name = '')`
- This route will not execute a registered global middleware
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareAdd($name = '', $params = [])`
- Register that this route must pass by a registered middleware
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareAppend($name = '', $function)`
- Append a ad-hock middleware to this specific route
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setWeight($weigth = 0)`
- Define the priority of this route on the execution chain
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setName($name)`
- Add a property name for the route object
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setTag($key = '', $value = '')`
- Add a custom arbitrary tag on the route object
## Other resources
https://stackoverflow.com/questions/8054165/using-put-method-in-html-form
Executable → Regular
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name" : "urfat/routes", "name" : "inforsistemas/routes",
"description" : "Different Routes", "description" : "Different Routes",
"type" : "library", "type" : "library",
"authors" : [ "authors" : [
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace Routes;
enum HTTPCodes: string
{
// Informational 1xx
case 100 = 'Continue';
case 101 = 'Switching Protocols';
// Successful 2xx
case 200 = 'OK';
case 201 = 'Created';
case 202 = 'Accepted';
case 203 = 'Non-Authoritative Information';
case 204 = 'No Content';
case 205 = 'Reset Content';
case 206 = 'Partial Content';
// Redirection 3xx
case 300 = 'Multiple Choices';
case 301 = 'Moved Permanently';
case 302 = 'Found';
case 303 = 'See Other';
case 304 = 'Not Modified';
case 305 = 'Use Proxy';
case 306 = '(Unused)';
case 307 = 'Temporary Redirect';
// Client Error 4xx
case 400 = 'Bad Request';
case 401 = 'Unauthorized';
case 402 = 'Payment Required';
case 403 = 'Forbidden';
case 404 = 'Not Found';
case 405 = 'Method Not Allowed';
case 406 = 'Not Acceptable';
case 407 = 'Proxy Authentication Required';
case 408 = 'Request Timeout';
case 409 = 'Conflict';
case 410 = 'Gone';
case 411 = 'Length Required';
case 412 = 'Precondition Failed';
case 413 = 'Request Entity Too Large';
case 414 = 'Request-URI Too Long';
case 415 = 'Unsupported Media Type';
case 416 = 'Requested Range Not Satisfiable';
case 417 = 'Expectation Failed';
// Server Error 5xx
case 500 = 'Internal Server Error';
case 501 = 'Not Implemented';
case 502 = 'Bad Gateway';
case 503 = 'Service Unavailable';
case 504 = 'Gateway Timeout';
case 505 = 'HTTP Version Not Supported';
}
+92 -81
View File
@@ -6,7 +6,11 @@ namespace Routes;
* *
*/ */
class Route { /**
* Summary of Route
*/
class Route
{
/* /*
* HTTP VERB * HTTP VERB
*/ */
@@ -18,6 +22,12 @@ class Route {
*/ */
public $_source; public $_source;
/**
* Tag Name
* @var string
*/
public $_name;
/* /*
* URI String * URI String
*/ */
@@ -66,7 +76,7 @@ class Route {
/* /*
* Can execute other route after this one? * Can execute other route after this one?
*/ */
public $_block = false; public $_block = true;
/* /*
* Is there a problem witch one? * Is there a problem witch one?
@@ -82,61 +92,15 @@ class Route {
* Middlewares to remove from the list * Middlewares to remove from the list
*/ */
public $_middlewaresToIgnore = Array(); public $_middlewaresToIgnore = Array();
/* /*
* From Klein * Arbitrary tag on a route
* HTTP status List
*/ */
protected static $httpMessages = array( public $_tags = Array();
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Successful 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
// Client Error 4xx
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
);
//======================================================= //=======================================================
function execute() { function execute()
{
//Middlewares with function or class method //Middlewares with function or class method
foreach ($this->_before as $key => $before) { foreach ($this->_before as $key => $before) {
if (!in_array($key, $this->_middlewaresToIgnore) && !$this->_ignore) { if (!in_array($key, $this->_middlewaresToIgnore) && !$this->_ignore) {
@@ -144,9 +108,9 @@ class Route {
$before = explode('@', $before); $before = explode('@', $before);
$class = new $before[0](); $class = new $before[0]();
$class->{$before[1]}(); $class->{$before[1]}();
}else if(is_array($before)){ } else if (is_array($before)) {
call_user_func($before['callback'], $before['params']); call_user_func($before['callback'], $before['params']);
}else{ } else {
call_user_func($before); call_user_func($before);
} }
} }
@@ -159,26 +123,26 @@ class Route {
$r = new \ReflectionMethod($segments[0], $segments[1]); $r = new \ReflectionMethod($segments[0], $segments[1]);
if (sizeof($r->getParameters()) > 0 && $r->getParameters()[0]->getClass() != NULL) { $firstType = count($r->getParameters()) > 0 ? $r->getParameters()[0]->getType() : null;
$element; if ($firstType instanceof \ReflectionNamedType && !$firstType->isBuiltin()) {
$element = $r->getParameters()[0]->getClass()->name; $element = $firstType->getName();
$element = new $element; $element = new $element;
if(isset($this->_params['id'])){ if (isset($this->_params['id'])) {
$element->load($this->_params['id']); $element->load($this->_params['id']);
} }
$this->_params['id'] = $element; $this->_params['id'] = $element;
} }
$class->{$segments[1]}(...array_values($this->_params)); $class->{$segments[1]}(...array_values($this->_params));
} else { } else {
$r = new \ReflectionFunction($callback); $r = new \ReflectionFunction($callback);
if(sizeof($r->getParameters()) > 0 && $r->getParameters()[0]->getClass() != NULL){ $firstType = count($r->getParameters()) > 0 ? $r->getParameters()[0]->getType() : null;
$element; if ($firstType instanceof \ReflectionNamedType && !$firstType->isBuiltin()) {
$element = $r->getParameters()[0]->getClass()->name; $element = $firstType->getName();
$element = new $element; $element = new $element;
if(isset($this->_params['id'])){ if (isset($this->_params['id'])) {
$element->load($this->_params['id']); $element->load($this->_params['id']);
} }
$this->_params['id'] = $element; $this->_params['id'] = $element;
} }
call_user_func_array($callback, $this->_params); call_user_func_array($callback, $this->_params);
} }
@@ -189,7 +153,8 @@ class Route {
} }
} }
function prepare() { function prepare()
{
$this->_segments = explode('/', $this->_uri); $this->_segments = explode('/', $this->_uri);
foreach ($this->_segments as $segment) { foreach ($this->_segments as $segment) {
@@ -199,6 +164,8 @@ class Route {
$this->_regex .= "\/[A-z]+"; $this->_regex .= "\/[A-z]+";
} else if (strpos($segment, 'd:') > -1) { } else if (strpos($segment, 'd:') > -1) {
$this->_regex .= "\/[A-z0-9]+"; $this->_regex .= "\/[A-z0-9]+";
} else if (strpos($segment, 's:') > -1) {
$this->_regex .= "\/[A-z0-9\-_]+";
} else if (strpos($segment, 'r:') > -1) { } else if (strpos($segment, 'r:') > -1) {
$this->_regex .= "\/[ -~]+"; $this->_regex .= "\/[ -~]+";
} else { } else {
@@ -209,7 +176,8 @@ class Route {
$this->_regex = "/^\/" . $this->_regex . "$/"; $this->_regex = "/^\/" . $this->_regex . "$/";
} }
function createIndexes() { function createIndexes()
{
foreach ($this->_segments as $key => $segment) { foreach ($this->_segments as $key => $segment) {
if (preg_match('/\[.*?\]$/', $segment)) { if (preg_match('/\[.*?\]$/', $segment)) {
$segment = trim(trim($segment, '['), ']'); $segment = trim(trim($segment, '['), ']');
@@ -219,55 +187,66 @@ class Route {
} }
} }
function setUri($uri) { function setUri($uri)
{
$this->_uri = $uri; $this->_uri = $uri;
return $this; return $this;
} }
function getSegments() { function getSegments()
{
return $this->_segments; return $this->_segments;
} }
function doBlock() { function doBlock()
{
$this->_block = true; $this->_block = true;
return $this; return $this;
} }
function notBlock() { function notBlock()
{
$this->_block = false; $this->_block = false;
return $this; return $this;
} }
function doIgnore() { function doIgnore()
{
$this->_ignore = true; $this->_ignore = true;
return $this; return $this;
} }
function notIgnore() { function notIgnore()
{
$this->_ignore = false; $this->_ignore = false;
return $this; return $this;
} }
function middlewareIgnore($name = '') { function middlewareIgnore($name = '')
{
$this->_middlewaresToIgnore[] = $name; $this->_middlewaresToIgnore[] = $name;
return $this; return $this;
} }
function middlewareAdd($name = '', $params) { function middlewareAdd($name = '', $params = [])
{
$this->_before[$name] = $params; $this->_before[$name] = $params;
return $this; return $this;
} }
function middlewareAppend($name = '', $function) { function middlewareAppend($name = '', $function)
{
$this->_before[$name] = $function; $this->_before[$name] = $function;
} }
function setWeight($weigth = 0) { function setWeight($weigth = 0)
{
$this->_weight = $weigth; $this->_weight = $weigth;
return $this; return $this;
} }
function setHttpError($code = 400, $message = null) { function setHttpError($code = 400, $message = null)
{
if ($message == null) { if ($message == null) {
$message = self::$httpMessages[$code]; $message = self::$httpMessages[$code];
} }
@@ -280,7 +259,8 @@ class Route {
return $this; return $this;
} }
function match($uri) { function match($uri)
{
//Wildcards allways match //Wildcards allways match
if (in_array('*', $this->_verb) || $this->_uri == '*') { if (in_array('*', $this->_verb) || $this->_uri == '*') {
return true; return true;
@@ -295,5 +275,36 @@ class Route {
return false; return false;
} }
} function name($name){
$this->_name = $name;
return $this;
}
function setTag($key = '', $value = ''){
$this->_tags[$key][] = $value;
return $this;
}
function hasTag($key){
return array_key_exists($key, $this->_tags);
}
function compress($group, $tag){
//$pattern = '/\[a:(\w+)\]/';
//$replacement = '/{{$1}}/';
//$route = preg_replace($pattern, $replacement, $this->_uri) );
$route = str_replace(['[i:', '[d:'], '{{', $this->_uri);
$route = str_replace([']', ']'], '}}', $route);
return [
'name' => $this->_name,
'group' => $group,
'tag' => $tag,
'verbs' => $this->_verb,
//'route' => preg_replace($pattern, $replacement, $this->_uri)
'route' => $route
];
}
}
+82 -40
View File
@@ -2,32 +2,36 @@
namespace Routes; namespace Routes;
class RouteCollection { class RouteCollection
{
private static $_routeCollection; private static $_routeCollection;
public $_uri = '/'; public $_uri = '/';
public $_routes = Array(); public $_routes = array();
private $_verb = ''; private $_verb = '';
private $_loadedFiles = Array(); private $_loadedFiles = array();
private $_errors = Array(); private $_errors = array();
private $_defaultMiddlewares = Array(); private $_defaultMiddlewares = array();
private $_middlewareSet = Array(); private $_middlewareSet = array();
private static $_verbsWhitelist = Array('*', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'CLI'); private static $_verbsWhitelist = array('*', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'CLI');
private static $_verbsWeb = Array('GET', 'POST', 'PUT', 'PATCH', 'DELETE'); private static $_verbsWeb = array('GET', 'POST', 'PUT', 'PATCH', 'DELETE');
public $_groupIn = false; public $_groupIn = false;
public $_groupBase = ''; public $_groupBase = '';
public $_groupList = []; public $_groupList = [];
public $_groups = [];
//SINGLETON============================================== //SINGLETON==============================================
private function __construct() { private function __construct()
{
} }
private static function newObj() { private static function newObj()
{
if (!isset(self::$_routeCollection)) { if (!isset(self::$_routeCollection)) {
self::$_routeCollection = new RouteCollection(); self::$_routeCollection = new RouteCollection();
if (php_sapi_name() == "cli") { if (php_sapi_name() == "cli") {
@@ -44,7 +48,8 @@ class RouteCollection {
/** /**
* *
*/ */
public static function getInstance() { public static function getInstance()
{
if (!isset(self::$_routeCollection)) { if (!isset(self::$_routeCollection)) {
return self::newObj(); return self::newObj();
} }
@@ -58,7 +63,8 @@ class RouteCollection {
* *
* @ctag\t RouteCollection->crawl() * @ctag\t RouteCollection->crawl()
*/ */
public function crawl($basepath = __DIR__, $filenames = Array('Routes.php', 'routes.php')) { public function crawl($basepath = __DIR__, $filenames = array('Routes.php', 'routes.php'))
{
$instance = self::getInstance(); $instance = self::getInstance();
$rdi = new \RecursiveDirectoryIterator($basepath); $rdi = new \RecursiveDirectoryIterator($basepath);
@@ -66,7 +72,7 @@ class RouteCollection {
foreach (new \RecursiveIteratorIterator($rdi) as $file) { foreach (new \RecursiveIteratorIterator($rdi) as $file) {
foreach ($filenames as $filename) { foreach ($filenames as $filename) {
// if (strpos($file, $filename) && $file[0] != '.') { // if (strpos($file, $filename) && $file[0] != '.') {
if (strpos($file, $filename) && !strpos($file, '.swp') ) { if (strpos($file, $filename) && !strpos($file, '.swp')) {
$instance->_loadedFiles[] = $file; $instance->_loadedFiles[] = $file;
} }
} }
@@ -79,7 +85,8 @@ class RouteCollection {
* Load the files with the routes * Load the files with the routes
* @ctag\t RouteCollection->loadRoutes() * @ctag\t RouteCollection->loadRoutes()
*/ */
function loadRoutes() { function loadRoutes()
{
$instance = self::getInstance(); $instance = self::getInstance();
foreach ($instance->_loadedFiles as $loadedFile) { foreach ($instance->_loadedFiles as $loadedFile) {
@@ -93,7 +100,8 @@ class RouteCollection {
* GET | POST | PUT | PATCH | DELETE | CLI * GET | POST | PUT | PATCH | DELETE | CLI
* *
*/ */
private function defineVerb() { private function defineVerb()
{
$verb = ''; $verb = '';
@@ -115,8 +123,9 @@ class RouteCollection {
/** /**
* *
*/ */
private function sort_routes() { private function sort_routes()
usort($this->_routes, function($a, $b) { {
usort($this->_routes, function ($a, $b) {
if ($a->_weight == $b->_weight) { if ($a->_weight == $b->_weight) {
return 0; return 0;
} }
@@ -127,7 +136,8 @@ class RouteCollection {
/** /**
* *
*/ */
function submit() { function submit()
{
global $ROUTE; global $ROUTE;
self::$_routeCollection->sort_routes(); self::$_routeCollection->sort_routes();
@@ -149,10 +159,11 @@ class RouteCollection {
$ROUTE = $route; $ROUTE = $route;
foreach ($route->_before as $key => $requestedMiddleware){ foreach ($route->_before as $key => $requestedMiddleware) {
$route->_before[$key] = Array( $route->_before[$key] = array(
'callback' => $this->_middlewareSet[$key], 'callback' => $this->_middlewareSet[$key],
'params' => $requestedMiddleware); 'params' => $requestedMiddleware
);
} }
$route->_before = array_merge($this->_defaultMiddlewares, $route->_before); $route->_before = array_merge($this->_defaultMiddlewares, $route->_before);
@@ -170,7 +181,7 @@ class RouteCollection {
//If Executed, interrupt route chain? //If Executed, interrupt route chain?
if ($route->_block) { if ($route->_block) {
return; break;
} }
} }
} }
@@ -187,7 +198,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::group('base',function(){}) * @ctag RouteCollection::group('base',function(){})
*/ */
static function group($base = '', $callback){ static function group($base = '', $callback, $name = '')
{
$collection = self::getInstance(); $collection = self::getInstance();
$collection->_groupList = []; $collection->_groupList = [];
$collection->_groupIn = true; $collection->_groupIn = true;
@@ -195,7 +207,9 @@ class RouteCollection {
call_user_func($callback); call_user_func($callback);
$collection->_groupBase = ''; $collection->_groupBase = '';
$collection->_groupIn = false; $collection->_groupIn = false;
return new RouteGroup($collection->_groupList); $group = new RouteGroup($collection->_groupList);
$collection->_groups[$name] = $group;
return $group;
} }
//DEFINITORS============================================= //DEFINITORS=============================================
@@ -204,7 +218,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::get('/url',function(){}) * @ctag RouteCollection::get('/url',function(){})
*/ */
static function get($uri, $callback, $weight = 0) { static function get($uri, $callback, $weight = 0)
{
return self::add('GET', $uri, $callback, $weight); return self::add('GET', $uri, $callback, $weight);
} }
@@ -212,7 +227,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::cli('/url',function(){}) * @ctag RouteCollection::cli('/url',function(){})
*/ */
static function cli($uri, $callback, $weight = 0) { static function cli($uri, $callback, $weight = 0)
{
return self::add('CLI', $uri, $callback, $weight); return self::add('CLI', $uri, $callback, $weight);
} }
@@ -220,7 +236,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::post('/url',function(){}) * @ctag RouteCollection::post('/url',function(){})
*/ */
static function post($uri, $callback, $weight = 0) { static function post($uri, $callback, $weight = 0)
{
return self::add('POST', $uri, $callback, $weight); return self::add('POST', $uri, $callback, $weight);
} }
@@ -228,7 +245,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::put('/url',function(){}) * @ctag RouteCollection::put('/url',function(){})
*/ */
static function put($uri, $callback, $weight = 0) { static function put($uri, $callback, $weight = 0)
{
return self::add('PUT', $uri, $callback, $weight); return self::add('PUT', $uri, $callback, $weight);
} }
@@ -236,7 +254,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::patch('/url',function(){}) * @ctag RouteCollection::patch('/url',function(){})
*/ */
static function patch($uri, $callback, $weight = 0) { static function patch($uri, $callback, $weight = 0)
{
return self::add('PATCH', $uri, $callback, $weight); return self::add('PATCH', $uri, $callback, $weight);
} }
@@ -245,7 +264,8 @@ class RouteCollection {
* @ctag RouteCollection::delete('/url',Controller@Method) * @ctag RouteCollection::delete('/url',Controller@Method)
* @ctag RouteCollection::delete('/url',function(){}) * @ctag RouteCollection::delete('/url',function(){})
*/ */
static function delete($uri, $callback, $weight = 0) { static function delete($uri, $callback, $weight = 0)
{
return self::add('DELETE', $uri, $callback, $weight); return self::add('DELETE', $uri, $callback, $weight);
} }
@@ -253,7 +273,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::resource('/url',function(){}) * @ctag RouteCollection::resource('/url',function(){})
*/ */
static function resource($uri) { static function resource($uri)
{
throw new Exception('Not implemented'); throw new Exception('Not implemented');
} }
@@ -262,10 +283,11 @@ class RouteCollection {
* @ctag RouteCollection::add('VERB','/url',function(){}) * @ctag RouteCollection::add('VERB','/url',function(){})
* @ctag RouteCollection::add('VERB','/url',Controller@Method) * @ctag RouteCollection::add('VERB','/url',Controller@Method)
*/ */
static function add($verb, $uri, $callback, $weight = 0) { static function add($verb, $uri, $callback, $weight = 0)
{
$route = new Route(); $route = new Route();
if(self::getInstance()->_groupIn){ if (self::getInstance()->_groupIn) {
$uri = self::getInstance()->_groupBase . $uri; $uri = self::getInstance()->_groupBase . $uri;
self::getInstance()->_groupList[] = &$route; self::getInstance()->_groupList[] = &$route;
} }
@@ -273,7 +295,7 @@ class RouteCollection {
if (is_array($verb)) { if (is_array($verb)) {
$route->_verb = array_map('strtoupper', $verb); $route->_verb = array_map('strtoupper', $verb);
} else if (strtoupper($verb) == 'WEB') { } else if (strtoupper($verb) == 'WEB') {
$route->_verb[] = self::_verbsWeb; $route->_verb = array_merge($route->_verb, self::$_verbsWeb);
} else { } else {
$route->_verb[] = strtoupper($verb); $route->_verb[] = strtoupper($verb);
} }
@@ -291,7 +313,8 @@ class RouteCollection {
/** /**
* *
*/ */
function addRoute(Route $route) { function addRoute(Route $route)
{
$this->_routes[] = $route; $this->_routes[] = $route;
} }
@@ -299,7 +322,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::addDefaultMiddleware('name',function(){}) * @ctag RouteCollection::addDefaultMiddleware('name',function(){})
*/ */
static function addDefaultMiddleware($name = '', $function) { static function addDefaultMiddleware($name = '', $function)
{
self::getInstance()->_defaultMiddlewares[$name] = $function; self::getInstance()->_defaultMiddlewares[$name] = $function;
return self::getInstance(); return self::getInstance();
} }
@@ -308,7 +332,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::addDefaultMiddleware('name',function(){}) * @ctag RouteCollection::addDefaultMiddleware('name',function(){})
*/ */
static function registerMiddleware($name = '', $function) { static function registerMiddleware($name = '', $function)
{
return self::getInstance()->_middlewareSet[$name] = $function; return self::getInstance()->_middlewareSet[$name] = $function;
} }
@@ -316,7 +341,8 @@ class RouteCollection {
* *
* @ctag RouteCollection::onHttpError(function(){}) * @ctag RouteCollection::onHttpError(function(){})
*/ */
static function onHttpError($code, $function) { static function onHttpError($code, $function)
{
$instance = self::getInstance(); $instance = self::getInstance();
} }
@@ -324,11 +350,27 @@ class RouteCollection {
* *
* @ctag RouteCollection::httpError($class) * @ctag RouteCollection::httpError($class)
*/ */
private function httpError(\stdClass $info) { private function httpError(\stdClass $info)
{
$info = (array) $info; $info = (array) $info;
foreach ($this->_errors as $error) { foreach ($this->_errors as $error) {
call_user_func_array($error, $info); call_user_func_array($error, $info);
} }
} }
public static function getGroupRoutesWithTags($group, $tag = '*')
{
$instance = self::getInstance();
if (!isset($instance->_groups[$group])) {
return [];
}
if (!isset($tag)) {
return $instance->_groups[$group];
}
return $instance->_groups[$group]->getRoutesWithTag($group, $tag);
}
} }
+47 -29
View File
@@ -2,77 +2,89 @@
namespace Routes; namespace Routes;
class RouteGroup{ class RouteGroup
{
private $_routeGroup = []; private $_routeGroup = [];
function __construct($group){ function __construct($group)
{
$this->setGroup($group); $this->setGroup($group);
} }
function setGroup($group){ function setGroup($group)
$this->_routeGroup = $group; {
$this->_routeGroup = $group;
} }
function doBlock() { function doBlock()
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_block = true; $route->_block = true;
} }
return $this; return $this;
} }
function notBlock() { function notBlock()
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_block = false; $route->_block = false;
} }
return $this; return $this;
} }
function doIgnore() { function doIgnore()
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_ignore = true; $route->_ignore = true;
} }
return $this; return $this;
} }
function notIgnore() { function notIgnore()
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_ignore = false; $route->_ignore = false;
} }
return $this; return $this;
} }
function middlewareIgnore($name = '') { function middlewareIgnore($name = '')
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_middlewaresToIgnore[] = $name; $route->_middlewaresToIgnore[] = $name;
} }
return $this; return $this;
} }
function middlewareAdd($name = '') { function middlewareAdd($name = '', $function)
foreach($this->_routeGroup as $route){ {
$route->_before[$name] = $function; foreach ($this->_routeGroup as $route) {
} $route->_before[] = $name;
}
return $this; return $this;
} }
function middlewareAppend($name = '', $function) { function middlewareAppend($name = '', $function)
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_before[$name] = $function; $route->_before[$name] = $function;
} }
return $this; return $this;
} }
function setWeight($weigth = 0) { function setWeight($weigth = 0)
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
$route->_weight = $weigth; $route->_weight = $weigth;
} }
return $this; return $this;
} }
function setHttpError($code = 400, $message = null) { function setHttpError($code = 400, $message = null)
foreach($this->_routeGroup as $route){ {
foreach ($this->_routeGroup as $route) {
if ($message == null) { if ($message == null) {
$message = self::$httpMessages[$code]; $message = self::$httpMessages[$code];
} }
@@ -86,4 +98,10 @@ class RouteGroup{
return $this; return $this;
} }
function getRoutesWithTag($group, $tag){
return array_filter(array_map(function($route) use($group, $tag){
return $route->hasTag($tag) ? $route->compress($group, $tag) : null;
}, $this->_routeGroup));
}
} }