Files
typecho/var/Typecho/Router.php
joyqi 3caebb3b20 v1.3.0 (#1661)
* Add feed widget

* add feed render

* Add CommentPage widget

* New theme (#1390)

* 调整忽略目录

* add theme

* fix theme scss build

Co-authored-by: fen <f3nb0x@gmail.com>

* s/is_writeable/is_writable/g

* New upgrade method

* merge new fixes from master

* add pgsql ssl mode support (ref #1600) (#1623)

* Feat/code refactor (#1626)

* remove all magic methods, add type for class properties

* refactor codes

* fix all

* refactor code

* fix type

* fix all

* fix request is method

* fix all

* fix router

* fix get page

* fix 1.3.0 upgrade

* [feat] support high resolution avatar

* fix types in i18n component

* Implement Ctrl+S or Command+S for save draft (#1628)

* Implement Ctrl+S or Command+S for save draft

* rename

* add Typecho.savePost

* fix upload file size

* add new uploader

* replace new uploader

* fix textarea change

* fix preview

* refactor post edit

* fix issue

* fix page edit

---------

Co-authored-by: joyqi <joyqi@segmentfault.com>
Co-authored-by: joyqi <magike.net@gmail.com>

* fix #1632

* Add svg to image types

* Feat/tree pages (#1646)

* add tree trait

* finish category tree trait

* support select fields

* fix select fields

* refactor admin trait

* fix draft status

* Add new contents type "revision"

* minor refactor

* add more tree view abstracts

* add tree trait to pages

* get ready for tree view pages

* improve page edit

* fix revision

* fix slug

* add router params delegate

* fix params delegate

* fix

* fix

* fix all

* fix all

* fix tree

* fix page link

* fix feed

* fix page

* fix permalink

* fix permalink input

* fix offset query

* Support IDN (#1629)

* Support IDN

* use js

* Optimize code

* Optimize code

* fix URL script

* remove unnecessary use

---------

Co-authored-by: joyqi <joyqi@segmentfault.com>

* fix input element

* fix #1651, close #1653

* Use json instead of serialize (#1624)

* Use json instead of serialize

* Fix Upgrade code

* add tree trait

* finish category tree trait

* support select fields

* fix select fields

* refactor admin trait

* fix draft status

* Add new contents type "revision"

* minor refactor

* add more tree view abstracts

* add tree trait to pages

* get ready for tree view pages

* improve page edit

* fix revision

* fix slug

* add router params delegate

* fix params delegate

* fix

* fix

* fix all

* fix all

* fix tree

* fix page link

* fix feed

* fix page

* fix permalink

* fix permalink input

* fix offset query

* Fix typo

* remove proxy methods

* remove unnecessary useage

---------

Co-authored-by: joyqi <joyqi@segmentfault.com>
Co-authored-by: joyqi <magike.net@gmail.com>

* Fix Prevent XSS vulnerability in default theme (#1654)

* Fix Prevent XSS vulnerability in default theme

* Update var/Typecho/Db/Adapter/Pdo.php

* fix the getter

---------

Co-authored-by: joyqi <joyqi@segmentfault.com>

* add throwCallback to widget response

* fix: cut down fields when selecting recent posts

* fix typo errors

* fix typo errors

* fix http client cookie

* add throw finish

* fix theme lang

* fix default theme

* fix query

* add open graph and twitter card support
add canonical link

* fix canonical link meta

* fix theme classic-22

* remove unnecessary scss file when packaging

* init plugin signal

* improve: remove feather-icon js file

* fix: typo

* improve: post detail layout

* fix tags saving

* improve: nav search

* fix: theme screenshot

* fix: theme page layout

* remove php 7.2/7.3 env

---------

Co-authored-by: fen <f3nb0x@gmail.com>
Co-authored-by: Lu Fei <52o@qq52o.cn>
2023-12-30 23:02:25 +08:00

192 lines
4.6 KiB
PHP

<?php
namespace Typecho;
use Typecho\Router\ParamsDelegateInterface;
use Typecho\Router\Parser;
use Typecho\Router\Exception as RouterException;
/**
* Typecho组件基类
*
* @package Router
*/
class Router
{
/**
* 当前路由名称
*
* @var string
*/
public static string $current;
/**
* 已经解析完毕的路由表配置
*
* @var array
*/
private static array $routingTable = [];
/**
* 是否已经匹配过,防止递归匹配
*
* @var bool
*/
private static bool $matched = false;
/**
* 解析路径
*
* @param string $pathInfo 全路径
* @param mixed $parameter 输入参数
* @param bool $once 是否只匹配一次
* @return false|Widget
* @throws \Exception
*/
public static function match(string $pathInfo, $parameter = null, bool $once = true)
{
if ($once && self::$matched) {
throw new RouterException("Path '{$pathInfo}' not found", 404);
}
self::$matched = true;
foreach (self::route($pathInfo) as $result) {
[$route, $params] = $result;
try {
return Widget::widget($route['widget'], $parameter, $params);
} catch (\Exception $e) {
if (404 == $e->getCode()) {
Widget::destroy($route['widget']);
continue;
}
throw $e;
}
}
return false;
}
/**
* 路由分发函数
*
* @throws RouterException|\Exception
*/
public static function dispatch()
{
/** 获取PATHINFO */
$pathInfo = Request::getInstance()->getPathInfo();
foreach (self::route($pathInfo) as $result) {
[$route, $params] = $result;
try {
$widget = Widget::widget($route['widget'], null, $params);
if (isset($route['action'])) {
$widget->{$route['action']}();
}
return;
} catch (\Exception $e) {
if (404 == $e->getCode()) {
Widget::destroy($route['widget']);
continue;
}
throw $e;
}
}
/** 载入路由异常支持 */
throw new RouterException("Path '{$pathInfo}' not found", 404);
}
/**
* 路由反解析函数
*
* @param string $name 路由配置表名称
* @param mixed $value 路由填充值
* @param string|null $prefix 最终合成路径的前缀
* @return string
*/
public static function url(
string $name,
$value = null,
?string $prefix = null
): string {
if (!isset(self::$routingTable[$name])) {
return '#';
}
$route = self::$routingTable[$name];
//交换数组键值
$pattern = [];
foreach ($route['params'] as $param) {
if (is_array($value) && isset($value[$param])) {
$pattern[$param] = $value[$param];
} elseif ($value instanceof ParamsDelegateInterface) {
$pattern[$param] = $value->getRouterParam($param);
} else {
$pattern[$param] = '{' . $param . '}';
}
}
return Common::url(vsprintf($route['format'], $pattern), $prefix);
}
/**
* 设置路由器默认配置
*
* @param mixed $routes 配置信息
* @return void
*/
public static function setRoutes($routes)
{
if (isset($routes[0])) {
self::$routingTable = $routes[0];
} else {
/** 解析路由配置 */
$parser = new Parser($routes);
self::$routingTable = $parser->parse();
}
}
/**
* 获取路由信息
*
* @param string $routeName 路由名称
* @return mixed
*/
public static function get(string $routeName)
{
return self::$routingTable[$routeName] ?? null;
}
/**
* @param string $pathInfo
* @return \Generator
* @throws \Exception
*/
private static function route(string $pathInfo): \Generator
{
foreach (self::$routingTable as $key => $route) {
if (preg_match($route['regx'], $pathInfo, $matches)) {
self::$current = $key;
/** 载入参数 */
$params = null;
if (!empty($route['params'])) {
unset($matches[0]);
$params = array_combine($route['params'], $matches);
}
yield [$route, $params];
}
}
}
}