new pisilinux web sites
This commit is contained in:
@@ -0,0 +1,412 @@
|
||||
<?php namespace ZN\Routing;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Base;
|
||||
use ZN\Lang;
|
||||
use ZN\Helper;
|
||||
use ZN\Kernel;
|
||||
use ZN\Config;
|
||||
use ZN\Request;
|
||||
use ZN\Response;
|
||||
use ZN\Datatype;
|
||||
use ZN\Singleton;
|
||||
use ZN\Request\URI;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
|
||||
class Route extends FilterProperties implements RouteInterface
|
||||
{
|
||||
use PropertyCreatorTrait;
|
||||
|
||||
/**
|
||||
* Run direct show 404 page
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $direct = false;
|
||||
|
||||
/**
|
||||
* Keeps Container Data
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $container, $useRunMethod = false;
|
||||
|
||||
/**
|
||||
* Keeps Array Data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $route = [], $routes = [], $status = [], $setFilters = [], $recursion = [], $recursionFilters = [], $allFilterKeys = [], $lines;
|
||||
|
||||
/**
|
||||
* Keeps routing config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $getConfig;
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*
|
||||
* Get route configuration.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->getConfig = Config::get('Routing');
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Destructor
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if( $this->useRunMethod === true && empty($this->status) )
|
||||
{
|
||||
$this->redirectShow404(CURRENT_CFUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run direct show 404 page
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function direct()
|
||||
{
|
||||
$this->direct = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Route Show404
|
||||
*
|
||||
* @param string $controllerAndMethod
|
||||
*/
|
||||
public function show404(string $controllerAndMethod)
|
||||
{
|
||||
if( $this->direct === true )
|
||||
{
|
||||
Config::set('Routing', 'runWithoutRedirect', $controllerAndMethod);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( empty( $this->route ) )
|
||||
{
|
||||
$s404 = '404';
|
||||
$this->change('{start}404{end}');
|
||||
}
|
||||
|
||||
Config::set('Routing', 'show404', $s404 ?? $this->route);
|
||||
|
||||
$this->uri($controllerAndMethod, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Container
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function container(callable $callback)
|
||||
{
|
||||
$current = count(debug_backtrace(2));
|
||||
|
||||
# 6.55.4.32[added] recursion container
|
||||
$recursion = $this->recursion;
|
||||
$recursionFilters = $this->recursionFilters;
|
||||
|
||||
# Calculates the number of inclusive recursion.
|
||||
# Rearranges the filters according to this calculation.
|
||||
if( count($recursion) > 1 ) for( $i = count($recursion) - 1; $i >= 0; $i-- )
|
||||
{
|
||||
if( $recursion[$i] < $current )
|
||||
{
|
||||
$this->filters = array_merge($recursionFilters[$i], $this->filters);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->recursion[] = $current;
|
||||
$this->recursionFilters[] = $this->filters;
|
||||
|
||||
$callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Filters
|
||||
*/
|
||||
public function filter()
|
||||
{
|
||||
foreach( array_unique($this->allFilterKeys) as $filter )
|
||||
{
|
||||
new Filter($filter, $this->setFilters, $this->getConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets old URI
|
||||
*
|
||||
* @param string $path = NULL
|
||||
*/
|
||||
public function uri(?string $path = NULL)
|
||||
{
|
||||
$path = $this->setPath($path, $routeConfig);
|
||||
|
||||
$container = debug_backtrace(2)[2];
|
||||
|
||||
$this->setContainerFilters($container);
|
||||
|
||||
$this->setFilters($path);
|
||||
|
||||
$this->changeRouteURI($path, $routeConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all route
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
if( ! empty($this->routes) )
|
||||
{
|
||||
$config = $this->getConfig;
|
||||
|
||||
Config::set('Routing', 'changeUri', array_merge($this->routes['changeUri'], $config['changeUri']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change URI
|
||||
*
|
||||
* @param string $route
|
||||
*
|
||||
* @return Route
|
||||
*/
|
||||
public function change(string $route) : Route
|
||||
{
|
||||
$route = trim($route, '/');
|
||||
$return = true;
|
||||
$routeSegment = explode('/', $route);
|
||||
|
||||
// Database Routing
|
||||
$route = $this->database($route, $routeSegment, $return);
|
||||
|
||||
if( empty($return) )
|
||||
{
|
||||
$this->route = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect Show 404
|
||||
*
|
||||
* @param string $function
|
||||
* @param string $lang
|
||||
* @param report
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function redirectShow404(string $function, string $lang = 'callUserFuncArrayError', string $report = 'SystemCallUserFuncArrayError')
|
||||
{
|
||||
if( ! $routeShow404 = $this->getConfig['show404'] )
|
||||
{
|
||||
Helper::report('Error', Lang::default('ZN\CoreDefaultLanguage')::select('Error', $lang, $function), $report);
|
||||
|
||||
exit(Errors::message('Error', $lang, $function));
|
||||
}
|
||||
else
|
||||
{
|
||||
Response::redirect($routeShow404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected set container filters
|
||||
*/
|
||||
protected function setContainerFilters($container)
|
||||
{
|
||||
$line = $container['line'];
|
||||
$func = $container['function'];
|
||||
|
||||
if( $func === 'container' )
|
||||
{
|
||||
if( isset($this->lines[$line]) )
|
||||
{
|
||||
$this->filters = array_merge($this->lines[$line], $this->filters); // @codeCoverageIgnore
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->lines[$line] = $this->filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected set path
|
||||
*/
|
||||
protected function setPath($path, &$routeConfig)
|
||||
{
|
||||
$path = rtrim($path ?? '', '/');
|
||||
|
||||
$routeConfig = $this->getConfig;
|
||||
|
||||
if( ! strstr($path, '/') )
|
||||
{
|
||||
$path = Base::suffix($path) . $routeConfig['openFunction'];
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected change route uri
|
||||
*/
|
||||
protected function changeRouteURI($path, $routeConfig)
|
||||
{
|
||||
if( empty($this->route) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$configPatternType = $routeConfig['patternType'];
|
||||
|
||||
if( $configPatternType === 'classic' )
|
||||
{
|
||||
$routeString = Singleton::class('ZN\Regex')->special2classic($this->route);
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
elseif( $configPatternType === 'special' )
|
||||
{
|
||||
$routeString = $this->route;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
# 5.3.21[edited] is empty
|
||||
if( trim($routeString ?? '', '/') )
|
||||
{
|
||||
$this->routes['changeUri'][$routeString] = $this->getStringRoute($path, $this->route)[$this->route];
|
||||
}
|
||||
|
||||
$this->route = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected routing database
|
||||
*/
|
||||
protected function database($route, $routeSegment, &$return)
|
||||
{
|
||||
return preg_replace_callback
|
||||
(
|
||||
'/\[(?<table>\w+|\.)\:(?<column>\w+|\.)(\s*\,\s*(?<separator>json|serial|separator)(\:(?<key>.*?))*)*\]/i',
|
||||
function($match) use (&$count, &$return, &$routeSegment)
|
||||
{
|
||||
$count = key(preg_grep('/' . preg_quote($match[0], '/') . '/', $routeSegment));
|
||||
unset($routeSegment[$count]);
|
||||
$decoder = $match['separator'] ?? NULL;
|
||||
$value = $val = URI::segment($count + 1);
|
||||
$column = $select = $match['column'];
|
||||
$dbClass = Singleton::class('ZN\Database\DB');
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
# Json, Serial or Separator
|
||||
if( $decoder !== NULL )
|
||||
{
|
||||
$column .= ' like';
|
||||
$value = $dbClass->like($value, 'inside');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$return = $dbClass->select($select)->where($column, $value)->get($match['table'])->value();
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
# Json, Serial or Separator
|
||||
if( $decoder !== NULL )
|
||||
{
|
||||
$row = $match['key'] ?? Lang::get();
|
||||
$rows = $decoder::decode($return);
|
||||
$rowsArray = $decoder::decodeArray($return);
|
||||
$return = $rows->$row ?? NULL;
|
||||
|
||||
# Current Lang Manipulation
|
||||
if( $return !== $value && in_array($val, $rowsArray) )
|
||||
{
|
||||
$arrayTransform = array_flip($rowsArray);
|
||||
|
||||
$newRow = $arrayTransform[$val];
|
||||
$return = $rows->$newRow;
|
||||
|
||||
Lang::set($newRow);
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $return;
|
||||
|
||||
},
|
||||
$route
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Filter
|
||||
*/
|
||||
protected function setFilters($path)
|
||||
{
|
||||
$lowerPath = strtolower($path ?? '');
|
||||
|
||||
$filterKeys = array_keys($this->filters);
|
||||
|
||||
$this->allFilterKeys = array_merge($this->allFilterKeys, $filterKeys);
|
||||
|
||||
foreach( $filterKeys as $type ) if( isset($this->filters[$type]) )
|
||||
{
|
||||
$this->setFilters[$type . 's'][$lowerPath][$type] = $this->filters[$type];
|
||||
}
|
||||
|
||||
$this->filters = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected String Route
|
||||
*/
|
||||
protected function getStringRoute($functionName, $route)
|
||||
{
|
||||
preg_match_all('/\:\w+/', $route ?? '', $match);
|
||||
|
||||
$newMatch = [];
|
||||
|
||||
$matchAll = $match[0] ?? [];
|
||||
|
||||
foreach( $matchAll as $key => $val )
|
||||
{
|
||||
$key++; // @codeCoverageIgnore
|
||||
|
||||
$newMatch[] = "$$key"; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$changeRoute = str_replace($matchAll, $newMatch, $route ?? '');
|
||||
$changeRoute = str_replace(Datatype::divide($route, '/'), $functionName, $changeRoute);
|
||||
$route = [$route => $changeRoute];
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user