Bicycle/System/Classes/Request.php
Egor Isaev b516ca07dc Initial commit: Bicycle PHP MVC micro-framework
Core MVC, HTTP client, Session, Cookie, Config, HTTPException — 111 PHPUnit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 10:04:19 +03:00

177 lines
5.0 KiB
PHP

<?php
/**
* @package Bicycle
* @author Egor Isaev
* @description Request.php
* @copyright (c) 03/06/2026
*/
namespace System\Classes;
use System\Classes\HTTP\HTTPException;
use System\Classes\HTTP\Request as HTTPRequest;
class Request implements HTTPRequest
{
public static ?self $initial = null;
public static ?self $current = null;
private string $_uri;
private string $_controller = 'Index';
private string $_action = 'index';
private array $_params = [];
private string $_method = HTTPRequest::GET;
private array $_post = [];
private array $_get = [];
private ?string $_body = null;
private string $_requested_with = '';
private function __construct(string $uri)
{
$this->_uri = $uri;
$route = Route::resolve($uri);
$this->_controller = $route['controller'];
$this->_action = $route['action'];
$this->_params = $route['params'];
}
public static function factory(): static
{
$uri = self::detect_uri();
$instance = new static($uri);
if (self::$initial === null) {
self::$initial = $instance;
}
self::$current = $instance;
$instance->method($_SERVER['REQUEST_METHOD'] ?? HTTPRequest::GET);
$instance->query($_GET);
$instance->post($_POST);
$instance->_requested_with = strtolower($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '');
if ($instance->method() !== HTTPRequest::GET) {
$body = file_get_contents('php://input');
if ($body !== false && $body !== '') {
$instance->body($body);
}
}
return $instance;
}
public static function detect_uri(): string
{
if (!empty($_SERVER['PATH_INFO'])) {
$uri = $_SERVER['PATH_INFO'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$uri = $_SERVER['REQUEST_URI'];
if ($path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)) {
$uri = $path;
}
$uri = rawurldecode($uri);
} elseif (isset($_SERVER['PHP_SELF'])) {
$uri = $_SERVER['PHP_SELF'];
} else {
$uri = '/';
}
return trim($uri, '/');
}
public function execute(): Response
{
$method = lcfirst($this->_action) . 'Action';
$parts = explode('/', $this->_controller);
$file = DOCROOT . '/App/Controller/' . implode('/', array_map('ucfirst', $parts)) . 'Controller.php';
if (!file_exists($file)) {
return HTTPException::factory(404)->get_response();
}
require_once $file;
$class = 'App\\Controller\\' . implode('\\', array_map('ucfirst', $parts)) . 'Controller';
if (!method_exists($class, $method)) {
return HTTPException::factory(404)->get_response();
}
return (new Response())->body((new $class())->$method());
}
public function method(?string $method = null): string|static
{
if ($method === null) {
return $this->_method;
}
$this->_method = strtoupper($method);
return $this;
}
public function post(null|string|array $key = null, mixed $value = null): null|array|string|static
{
if (is_array($key)) {
$this->_post = $key;
return $this;
}
if ($key === null) {
return $this->_post;
}
if ($value === null) {
return $this->_post[$key] ?? null;
}
$this->_post[$key] = $value;
return $this;
}
public function query(null|string|array $key = null, mixed $value = null): null|array|string|static
{
if (is_array($key)) {
$this->_get = $key;
return $this;
}
if ($key === null) {
return $this->_get;
}
if ($value === null) {
return $this->_get[$key] ?? null;
}
$this->_get[$key] = $value;
return $this;
}
public function body(?string $content = null): string|static
{
if ($content === null) {
return $this->_body ?? '';
}
$this->_body = $content;
return $this;
}
public function requested_with(?string $value = null): string|static
{
if ($value === null) {
return $this->_requested_with;
}
$this->_requested_with = strtolower($value);
return $this;
}
public function is_ajax(): bool
{
return $this->_requested_with === 'xmlhttprequest';
}
public function controller(): string { return $this->_controller; }
public function action(): string { return $this->_action; }
public function params(): array { return $this->_params; }
public function uri(): string { return $this->_uri; }
public function param(int $index, mixed $default = null): mixed
{
return $this->_params[$index] ?? $default;
}
}