first commit
This commit is contained in:
+419
@@ -0,0 +1,419 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Webman;
|
||||
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteCollector;
|
||||
use Webman\Route\Route as RouteObject;
|
||||
use function FastRoute\simpleDispatcher;
|
||||
|
||||
/**
|
||||
* Class Route
|
||||
* @package Webman
|
||||
*/
|
||||
class Route
|
||||
{
|
||||
/**
|
||||
* @var Route
|
||||
*/
|
||||
protected static $_instance = null;
|
||||
|
||||
/**
|
||||
* @var GroupCountBased
|
||||
*/
|
||||
protected static $_dispatcher = null;
|
||||
|
||||
/**
|
||||
* @var RouteCollector
|
||||
*/
|
||||
protected static $_collector = null;
|
||||
|
||||
/**
|
||||
* @var null|callable
|
||||
*/
|
||||
protected static $_fallback = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_nameList = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $_groupPrefix = '';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected static $_disableDefaultRoute = [];
|
||||
|
||||
/**
|
||||
* @var RouteObject[]
|
||||
*/
|
||||
protected static $_allRoutes = [];
|
||||
|
||||
/**
|
||||
* @var RouteObject[]
|
||||
*/
|
||||
protected $_routes = [];
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function get(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('GET', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function post(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('POST', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function put(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('PUT', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function patch(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('PATCH', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function delete(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('DELETE', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function head(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('HEAD', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function options(string $path, $callback)
|
||||
{
|
||||
return static::addRoute('OPTIONS', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function any(string $path, $callback)
|
||||
{
|
||||
return static::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function add($method, string $path, $callback)
|
||||
{
|
||||
return static::addRoute($method, $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|callable $path
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public static function group($path, callable $callback = null)
|
||||
{
|
||||
if ($callback === null) {
|
||||
$callback = $path;
|
||||
$path = '';
|
||||
}
|
||||
$previous_group_prefix = static::$_groupPrefix;
|
||||
static::$_groupPrefix = $previous_group_prefix . $path;
|
||||
$instance = static::$_instance = new static;
|
||||
static::$_collector->addGroup($path, $callback);
|
||||
static::$_instance = null;
|
||||
static::$_groupPrefix = $previous_group_prefix;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public static function resource(string $name, string $controller, array $options = [])
|
||||
{
|
||||
$name = trim($name, '/');
|
||||
if (\is_array($options) && !empty($options)) {
|
||||
$diff_options = \array_diff($options, ['index', 'create', 'store', 'update', 'show', 'edit', 'destroy', 'recovery']);
|
||||
if (!empty($diff_options)) {
|
||||
foreach ($diff_options as $action) {
|
||||
static::any("/{$name}/{$action}[/{id}]", [$controller, $action])->name("{$name}.{$action}");
|
||||
}
|
||||
}
|
||||
// 注册路由 由于顺序不同会导致路由无效 因此不适用循环注册
|
||||
if (\in_array('index', $options)) static::get("/{$name}", [$controller, 'index'])->name("{$name}.index");
|
||||
if (\in_array('create', $options)) static::get("/{$name}/create", [$controller, 'create'])->name("{$name}.create");
|
||||
if (\in_array('store', $options)) static::post("/{$name}", [$controller, 'store'])->name("{$name}.store");
|
||||
if (\in_array('update', $options)) static::put("/{$name}/{id}", [$controller, 'update'])->name("{$name}.update");
|
||||
if (\in_array('show', $options)) static::get("/{$name}/{id}", [$controller, 'show'])->name("{$name}.show");
|
||||
if (\in_array('edit', $options)) static::get("/{$name}/{id}/edit", [$controller, 'edit'])->name("{$name}.edit");
|
||||
if (\in_array('destroy', $options)) static::delete("/{$name}/{id}", [$controller, 'destroy'])->name("{$name}.destroy");
|
||||
if (\in_array('recovery', $options)) static::put("/{$name}/{id}/recovery", [$controller, 'recovery'])->name("{$name}.recovery");
|
||||
} else {
|
||||
//为空时自动注册所有常用路由
|
||||
if (\method_exists($controller, 'index')) static::get("/{$name}", [$controller, 'index'])->name("{$name}.index");
|
||||
if (\method_exists($controller, 'create')) static::get("/{$name}/create", [$controller, 'create'])->name("{$name}.create");
|
||||
if (\method_exists($controller, 'store')) static::post("/{$name}", [$controller, 'store'])->name("{$name}.store");
|
||||
if (\method_exists($controller, 'update')) static::put("/{$name}/{id}", [$controller, 'update'])->name("{$name}.update");
|
||||
if (\method_exists($controller, 'show')) static::get("/{$name}/{id}", [$controller, 'show'])->name("{$name}.show");
|
||||
if (\method_exists($controller, 'edit')) static::get("/{$name}/{id}/edit", [$controller, 'edit'])->name("{$name}.edit");
|
||||
if (\method_exists($controller, 'destroy')) static::delete("/{$name}/{id}", [$controller, 'destroy'])->name("{$name}.destroy");
|
||||
if (\method_exists($controller, 'recovery')) static::put("/{$name}/{id}/recovery", [$controller, 'recovery'])->name("{$name}.recovery");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RouteObject[]
|
||||
*/
|
||||
public static function getRoutes()
|
||||
{
|
||||
return static::$_allRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* disableDefaultRoute.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function disableDefaultRoute($plugin = '')
|
||||
{
|
||||
static::$_disableDefaultRoute[$plugin] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasDisableDefaultRoute($plugin = '')
|
||||
{
|
||||
return static::$_disableDefaultRoute[$plugin] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $middleware
|
||||
* @return $this
|
||||
*/
|
||||
public function middleware($middleware)
|
||||
{
|
||||
foreach ($this->_routes as $route) {
|
||||
$route->middleware($middleware);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RouteObject $route
|
||||
*/
|
||||
public function collect(RouteObject $route)
|
||||
{
|
||||
$this->_routes[] = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param RouteObject $instance
|
||||
*/
|
||||
public static function setByName(string $name, RouteObject $instance)
|
||||
{
|
||||
static::$_nameList[$name] = $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return null|RouteObject
|
||||
*/
|
||||
public static function getByName(string $name)
|
||||
{
|
||||
return static::$_nameList[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
* @return array
|
||||
*/
|
||||
public static function dispatch($method, string $path)
|
||||
{
|
||||
return static::$_dispatcher->dispatch($method, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return callable|false|string[]
|
||||
*/
|
||||
public static function convertToCallable(string $path, $callback)
|
||||
{
|
||||
if (\is_string($callback) && \strpos($callback, '@')) {
|
||||
$callback = \explode('@', $callback, 2);
|
||||
}
|
||||
|
||||
if (!\is_array($callback)) {
|
||||
if (!\is_callable($callback)) {
|
||||
$call_str = \is_scalar($callback) ? $callback : 'Closure';
|
||||
echo "Route $path $call_str is not callable\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$callback = \array_values($callback);
|
||||
if (!isset($callback[1]) || !\class_exists($callback[0]) || !\method_exists($callback[0], $callback[1])) {
|
||||
echo "Route $path " . \json_encode($callback) . " is not callable\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $methods
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
protected static function addRoute($methods, string $path, $callback)
|
||||
{
|
||||
$route = new RouteObject($methods, static::$_groupPrefix . $path, $callback);
|
||||
static::$_allRoutes[] = $route;
|
||||
|
||||
if ($callback = static::convertToCallable($path, $callback)) {
|
||||
static::$_collector->addRoute($methods, $path, ['callback' => $callback, 'route' => $route]);
|
||||
}
|
||||
if (static::$_instance) {
|
||||
static::$_instance->collect($route);
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $paths
|
||||
* @return void
|
||||
*/
|
||||
public static function load($paths)
|
||||
{
|
||||
if (!\is_array($paths)) {
|
||||
return;
|
||||
}
|
||||
static::$_dispatcher = simpleDispatcher(function (RouteCollector $route) use ($paths) {
|
||||
Route::setCollector($route);
|
||||
foreach ($paths as $config_path) {
|
||||
$route_config_file = $config_path . '/route.php';
|
||||
if (\is_file($route_config_file)) {
|
||||
require_once $route_config_file;
|
||||
}
|
||||
if (!is_dir($plugin_config_path = $config_path . '/plugin')) {
|
||||
continue;
|
||||
}
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($plugin_config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->getBaseName('.php') !== 'route') {
|
||||
continue;
|
||||
}
|
||||
$app_config_file = pathinfo($file, PATHINFO_DIRNAME) . '/app.php';
|
||||
if (!is_file($app_config_file)) {
|
||||
continue;
|
||||
}
|
||||
$app_config = include $app_config_file;
|
||||
if (empty($app_config['enable'])) {
|
||||
continue;
|
||||
}
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RouteCollector $route
|
||||
* @return void
|
||||
*/
|
||||
public static function setCollector(RouteCollector $route)
|
||||
{
|
||||
static::$_collector = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback
|
||||
* @param string $plugin
|
||||
* @return void
|
||||
*/
|
||||
public static function fallback(callable $callback, string $plugin = '')
|
||||
{
|
||||
static::$_fallback[$plugin] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable|null
|
||||
*/
|
||||
public static function getFallback(string $plugin = '')
|
||||
{
|
||||
return static::$_fallback[$plugin] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return void
|
||||
*/
|
||||
public static function container()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user