first commit

This commit is contained in:
root
2022-12-17 12:38:00 +00:00
commit 3e75b4fe06
573 changed files with 80324 additions and 0 deletions
+419
View File
@@ -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()
{
}
}