Add Request class and make Router::parseUrl() return an instance of it

This commit is contained in:
Kijin Sung 2023-10-29 23:32:49 +09:00
parent 986fc23043
commit a196706d7f
5 changed files with 242 additions and 57 deletions

View file

@ -8,6 +8,11 @@
#[AllowDynamicProperties] #[AllowDynamicProperties]
class Context class Context
{ {
/**
* Current request object
*/
protected $_current_request;
/** /**
* Request method * Request method
* @var string GET|POST|XMLRPC|JSON * @var string GET|POST|XMLRPC|JSON
@ -129,11 +134,6 @@ class Context
*/ */
private static $_init_called = false; private static $_init_called = false;
/**
* Current route information
*/
private static $_route_info = null;
/** /**
* object oFrontEndFileHandler() * object oFrontEndFileHandler()
* @var object * @var object
@ -239,15 +239,17 @@ class Context
if (in_array(self::$_instance->request_method, array('GET', 'POST', 'JSON'))) if (in_array(self::$_instance->request_method, array('GET', 'POST', 'JSON')))
{ {
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$route_info = Rhymix\Framework\Router::parseURL($method, RX_REQUEST_URL, Rhymix\Framework\Router::getRewriteLevel()); $request = Rhymix\Framework\Router::parseURL($method, RX_REQUEST_URL, Rhymix\Framework\Router::getRewriteLevel());
self::setRequestArguments($route_info->args); self::setRequestArguments($request->args);
self::$_route_info = $route_info;
} }
else else
{ {
$request = new Rhymix\Framework\Request;
self::setRequestArguments(); self::setRequestArguments();
} }
self::setUploadInfo(); self::setUploadInfo();
self::$_instance->_current_request = $request;
$request->args = get_object_vars(self::$_get_vars);
// If Rhymix is installed, get virtual site information. // If Rhymix is installed, get virtual site information.
if(self::isInstalled()) if(self::isInstalled())
@ -366,13 +368,13 @@ class Context
// start session // start session
if (\PHP_SAPI !== 'cli') if (\PHP_SAPI !== 'cli')
{ {
if (!isset(self::$_route_info->session) || self::$_route_info->session) if ($request->getRouteOption('enable_session'))
{ {
session_cache_limiter(''); session_cache_limiter('');
Rhymix\Framework\Session::checkSSO($site_module_info); Rhymix\Framework\Session::checkSSO($site_module_info);
Rhymix\Framework\Session::start(false); Rhymix\Framework\Session::start(false);
} }
if (!isset(self::$_route_info->cache_control) || self::$_route_info->cache_control) if ($request->getRouteOption('cache_control'))
{ {
if (!session_cache_limiter()) if (!session_cache_limiter())
{ {
@ -548,7 +550,7 @@ class Context
* @param object $db_info DB information * @param object $db_info DB information
* @return void * @return void
*/ */
public static function setDBInfo($db_info) public static function setDBInfo(object $db_info): void
{ {
self::$_instance->db_info = $db_info; self::$_instance->db_info = $db_info;
} }
@ -559,28 +561,39 @@ class Context
* @deprecated * @deprecated
* @return object DB information * @return object DB information
*/ */
public static function getDBInfo() public static function getDBInfo(): object
{ {
return self::$_instance->db_info; return self::$_instance->db_info ?? new \stdClass;
} }
/** /**
* Get current route information * Get current route information
* *
* @return object * @deprecated
* @return Rhymix\Framework\Request
*/ */
public static function getRouteInfo() public static function getRouteInfo(): Rhymix\Framework\Request
{ {
return self::$_route_info; return self::$_instance->_current_request;
} }
/** /**
* Return ssl status * Get the current request.
*
* @return Rhymix\Framework\Request
*/
public static function getCurrentRequest(): Rhymix\Framework\Request
{
return self::$_instance->_current_request;
}
/**
* Return SSL status
* *
* @deprecated * @deprecated
* @return object SSL status (none or always) * @return string (none or always)
*/ */
public static function getSSLStatus() public static function getSSLStatus(): string
{ {
return self::get('_use_ssl'); return self::get('_use_ssl');
} }

View file

@ -537,7 +537,7 @@ class HTMLDisplayHandler
} }
else else
{ {
if (Rhymix\Framework\Router::getRewriteLevel() === 2 && Context::getRouteInfo()->url !== '') if (Rhymix\Framework\Router::getRewriteLevel() === 2 && Context::getCurrentRequest()->url !== '')
{ {
$canonical_url = Rhymix\Framework\URL::getCurrentDomainURL(\RX_BASEURL . preg_replace('/\?.*$/', '', \RX_REQUEST_URL)); $canonical_url = Rhymix\Framework\URL::getCurrentDomainURL(\RX_BASEURL . preg_replace('/\?.*$/', '', \RX_REQUEST_URL));
} }

View file

@ -86,7 +86,7 @@ class ModuleHandler extends Handler
$this->mid = $mid ? $mid : Context::get('mid'); $this->mid = $mid ? $mid : Context::get('mid');
$this->document_srl = $document_srl ? (int) $document_srl : (int) Context::get('document_srl'); $this->document_srl = $document_srl ? (int) $document_srl : (int) Context::get('document_srl');
$this->module_srl = $module_srl ? (int) $module_srl : (int) Context::get('module_srl'); $this->module_srl = $module_srl ? (int) $module_srl : (int) Context::get('module_srl');
$this->route = Context::getRouteInfo() ?: new stdClass; $this->route = Context::getCurrentRequest() ?: new stdClass;
$this->is_mobile = Mobile::isFromMobilePhone(); $this->is_mobile = Mobile::isFromMobilePhone();
if($entry = Context::get('entry')) if($entry = Context::get('entry'))
{ {
@ -157,7 +157,7 @@ class ModuleHandler extends Handler
} }
// If the Router returned an error earlier, show an error here. // If the Router returned an error earlier, show an error here.
if($this->route && $this->route->status > 200) if($this->route && $this->route->getRouteStatus() > 200)
{ {
$this->error = 'msg_module_is_not_exists'; $this->error = 'msg_module_is_not_exists';
$this->error_detail = 'ERR_ROUTE_NOT_FOUND'; $this->error_detail = 'ERR_ROUTE_NOT_FOUND';

View file

@ -0,0 +1,187 @@
<?php
namespace Rhymix\Framework;
/**
* The request class.
*/
class Request
{
/**
* The request method.
*/
public $method = '';
/**
* The request URL, not including RX_BASEURL.
*/
public $url = '';
/**
* The requested host name and current domain information.
*/
public $hostname = '';
public $domain;
/**
* The protocol used.
*/
public $protocol = 'http';
/**
* The callback function for JSONP requests, also known as "JS callback" in XE.
*/
public $callback_function = '';
/**
* Routing information, request arguments, and options.
*/
protected $_route_status = 200;
protected $_route_options;
public $module = '';
public $mid = '';
public $act = '';
public $args = [];
/**
* Constructor.
*
* @param string $method
* @param string $url
* @param string $hostname
* @param string $protocol
*/
public function __construct(string $method = '', string $url = '', string $hostname = '', string $protocol = '')
{
// Set instance properties.
$this->method = $method ?: (\PHP_SAPI === 'cli' ? 'CLI' : \Context::getRequestMethod());
$this->url = $url ?: \RX_REQUEST_URL;
$this->hostname = $hostname ?: $_SERVER['HTTP_HOST'];
$this->protocol = \RX_SSL ? 'https' : 'http';
$this->callback_function = \Context::get('js_callback_func') ?: '';
// Initialize the arguments object.
$this->args = [];
// Initialize route options.
$this->_route_options = new \stdClass;
$this->_route_options->cache_control = true;
$this->_route_options->check_csrf = true;
$this->_route_options->is_forwarded = false;
$this->_route_options->is_indexable = true;
$this->_route_options->enable_session = true;
}
/**
* Get a request argument, optionally coerced into a type.
*
* @param string $name
* @param string $type
* @return mixed
*/
public function get(string $name, string $type = '')
{
$value = $this->args[$name] ?? null;
switch ($type)
{
case 'int': $value = (int)$value; break;
case 'float': $value = (float)$value; break;
case 'bool': $value = tobool($value); break;
}
return $value;
}
/**
* Get all request arguments.
*
* @return object
*/
public function getAll(): object
{
return (object)($this->args);
}
/**
* Get the complete URL of this request.
*
* @return string
*/
public function getFullUrl(): string
{
return sprintf('%s://%s%s%s', $this->protocol, $this->hostname, \RX_BASEURL, $this->url);
}
/**
* Get the HTTP method of this request.
*
* @return string
*/
public function getMethod(): string
{
return $this->method;
}
/**
* Get the JS callback function.
*
* @return string
*/
public function getCallbackFunction(): string
{
return $this->callback_function;
}
/**
* Get route status.
*
* @return int
*/
public function getRouteStatus(): int
{
return $this->_route_status;
}
/**
* Set route status.
*
* @param int $status
* @return void
*/
public function setRouteStatus(int $status): void
{
$this->_route_status = $status;
}
/**
* Get route options.
*
* @param string $name
* @return mixed
*/
public function getRouteOption(string $name)
{
return $this->_route_options->{$name} ?? null;
}
/**
* Get all route options.
*
* @return object
*/
public function getRouteOptions(): object
{
return $this->_route_options;
}
/**
* Set route option.
*
* @param string $name
* @param mixed $value
* @return void
*/
public function setRouteOption(string $name, $value): void
{
$this->_route_options->{$name} = $value;
}
}

View file

@ -90,21 +90,6 @@ class Router
protected static $_internal_forwarded_cache = array(); protected static $_internal_forwarded_cache = array();
protected static $_route_cache = array(); protected static $_route_cache = array();
/**
* Instance properties.
*/
public $status = 200;
public $url = '';
public $module = '';
public $mid = '';
public $act = '';
public $args = [];
public $is_forwarded = false;
public $check_csrf = true;
public $meta_noindex = false;
public $session = true;
public $cache_control = true;
/** /**
* Return the currently configured rewrite level. * Return the currently configured rewrite level.
* *
@ -130,12 +115,12 @@ class Router
* @param string $method * @param string $method
* @param string $url * @param string $url
* @param int $rewrite_level * @param int $rewrite_level
* @return self * @return Request
*/ */
public static function parseURL(string $method, string $url, int $rewrite_level): self public static function parseURL(string $method, string $url, int $rewrite_level): Request
{ {
// Prepare the return object. // Prepare the return object.
$result = new self; $result = new Request;
// Separate additional arguments from the URL. // Separate additional arguments from the URL.
$args = array(); $args = array();
@ -155,7 +140,7 @@ class Router
} }
if (function_exists('mb_check_encoding') && !mb_check_encoding($url, 'UTF-8')) if (function_exists('mb_check_encoding') && !mb_check_encoding($url, 'UTF-8'))
{ {
$result->status = 404; $result->setRouteStatus(404);
return $result; return $result;
} }
@ -223,7 +208,7 @@ class Router
$result->module = $action[0]; $result->module = $action[0];
$result->mid = $prefix; $result->mid = $prefix;
$result->act = $action[1]; $result->act = $action[1];
$result->is_forwarded = true; $result->setRouteOption('is_forwarded', true);
$result->args = $allargs; $result->args = $allargs;
self::_fillActionProperties($result); self::_fillActionProperties($result);
return $result; return $result;
@ -238,7 +223,7 @@ class Router
$result->module = $module_name; $result->module = $module_name;
$result->mid = $prefix_type === 'mid' ? $prefix : ''; $result->mid = $prefix_type === 'mid' ? $prefix : '';
$result->act = $internal_url; $result->act = $internal_url;
$result->is_forwarded = true; $result->setRouteOption('is_forwarded', true);
$result->args = $allargs; $result->args = $allargs;
self::_fillActionProperties($result); self::_fillActionProperties($result);
return $result; return $result;
@ -251,7 +236,7 @@ class Router
$result->module = $module_name; $result->module = $module_name;
$result->mid = $prefix_type === 'mid' ? $prefix : ''; $result->mid = $prefix_type === 'mid' ? $prefix : '';
$result->act = $action_info->error_handlers[404]; $result->act = $action_info->error_handlers[404];
$result->is_forwarded = false; $result->setRouteOption('is_forwarded', false);
$result->args = $allargs; $result->args = $allargs;
self::_fillActionProperties($result); self::_fillActionProperties($result);
return $result; return $result;
@ -271,7 +256,7 @@ class Router
$allargs = array_merge($args, $matches, ['act' => $action[1]]); $allargs = array_merge($args, $matches, ['act' => $action[1]]);
$result->module = $action[0]; $result->module = $action[0];
$result->act = $action[1]; $result->act = $action[1];
$result->is_forwarded = true; $result->setRouteOption('is_forwarded', true);
$result->args = $allargs; $result->args = $allargs;
self::_fillActionProperties($result); self::_fillActionProperties($result);
return $result; return $result;
@ -289,7 +274,7 @@ class Router
$result->module = $allargs['module'] ?? ''; $result->module = $allargs['module'] ?? '';
$result->mid = ($allargs['mid'] ?? '') ?: ''; $result->mid = ($allargs['mid'] ?? '') ?: '';
$result->act = ($allargs['act'] ?? '') ?: ''; $result->act = ($allargs['act'] ?? '') ?: '';
$result->is_forwarded = false; $result->setRouteOption('is_forwarded', false);
$result->args = $allargs; $result->args = $allargs;
self::_fillActionProperties($result); self::_fillActionProperties($result);
return $result; return $result;
@ -308,7 +293,7 @@ class Router
} }
else else
{ {
$result->status = 404; $result->setRouteStatus(404);
return $result; return $result;
} }
} }
@ -496,20 +481,20 @@ class Router
/** /**
* Fill additional properties of an action. * Fill additional properties of an action.
* *
* @param object $route * @param Request $request
* @param ?object $action * @param ?object $action
* @return void * @return void
*/ */
protected static function _fillActionProperties(object $route, ?object $action = null): void protected static function _fillActionProperties(Request $request, ?object $action = null): void
{ {
if (!$action) if (!$action)
{ {
if ($route->module && $route->act) if ($request->module && $request->act)
{ {
$action_info = \ModuleModel::getModuleActionXml($route->module); $action_info = \ModuleModel::getModuleActionXml($request->module);
if (isset($action_info->action->{$route->act})) if (isset($action_info->action->{$request->act}))
{ {
$action = $action_info->action->{$route->act}; $action = $action_info->action->{$request->act};
} }
} }
} }
@ -518,10 +503,10 @@ class Router
return; return;
} }
$route->check_csrf = ($action->check_csrf === 'false') ? false : true; $request->setRouteOption('check_csrf', ($action->check_csrf === 'false') ? false : true);
$route->meta_noindex = ($action->meta_noindex === 'true') ? true : false; $request->setRouteOption('is_indexable', ($action->meta_noindex === 'true') ? false : true);
$route->session = ($action->session === 'false') ? false : true; $request->setRouteOption('enable_session', ($action->session === 'false') ? false : true);
$route->cache_control = ($action->cache_control === 'false') ? false : true; $request->setRouteOption('cache_control', ($action->cache_control === 'false') ? false : true);
} }
/** /**