From d1713ce375fbf1bd8fa7cd4c85348d79169c971f Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 27 Apr 2026 10:50:29 +0100 Subject: [PATCH] Chore: Type class constants and expand Pint rule set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add explicit types to all 110 class constants across the public API (string/int/array) — leveraging PHP 8.3 typed constants now that the floor is 8.3. Expand pint.json beyond the bare `per` preset with rules that match common editor inspections, so CI catches what the editor flags: - native_function_invocation (@compiler_optimized, namespaced scope) - no_unused_imports, ordered_imports - no_useless_else, no_useless_return - no_empty_statement, no_empty_phpdoc, no_empty_comment - array_syntax (short), single_quote - trailing_comma_in_multiline Pint applied the new rules across the codebase (mainly prefixing compiler-optimized builtins with `\` in namespaced files and sorting imports). --- example/src/server.php | 2 +- pint.json | 25 ++- rector.php | 2 +- src/Http/Adapter/FPM/Request.php | 22 +-- src/Http/Adapter/FPM/Response.php | 8 +- src/Http/Adapter/Swoole/Request.php | 10 +- src/Http/Adapter/Swoole/Response.php | 2 +- src/Http/Adapter/Swoole/Server.php | 8 +- src/Http/Adapter/SwooleCoroutine/Server.php | 6 +- src/Http/Files.php | 22 +-- src/Http/Http.php | 46 ++--- src/Http/Request.php | 40 ++--- src/Http/Response.php | 188 ++++++++++---------- src/Http/Route.php | 4 +- src/Http/Router.php | 22 +-- src/Http/View.php | 42 ++--- tests/HttpTest.php | 110 ++++++------ tests/UtopiaFPMRequestTest.php | 2 +- tests/e2e/Client.php | 4 +- 19 files changed, 294 insertions(+), 271 deletions(-) diff --git a/example/src/server.php b/example/src/server.php index 792c639..8fa6d9e 100644 --- a/example/src/server.php +++ b/example/src/server.php @@ -2,9 +2,9 @@ require_once __DIR__ . '/../vendor/autoload.php'; +use Utopia\Http\Adapter\Swoole\Server; use Utopia\Http\Http; use Utopia\Http\Response; -use Utopia\Http\Adapter\Swoole\Server; use Utopia\Validator\Text; Http::get('/') diff --git a/pint.json b/pint.json index f9ec356..d338dee 100644 --- a/pint.json +++ b/pint.json @@ -1,3 +1,26 @@ { - "preset": "per" + "preset": "per", + "rules": { + "native_function_invocation": { + "include": ["@compiler_optimized"], + "scope": "namespaced", + "strict": true + }, + "no_unused_imports": true, + "ordered_imports": { + "sort_algorithm": "alpha" + }, + "no_useless_else": true, + "no_useless_return": true, + "no_empty_statement": true, + "no_empty_phpdoc": true, + "no_empty_comment": true, + "array_syntax": { + "syntax": "short" + }, + "single_quote": true, + "trailing_comma_in_multiline": { + "elements": ["arrays", "arguments", "parameters"] + } + } } diff --git a/rector.php b/rector.php index 64e1746..ac6e2f4 100644 --- a/rector.php +++ b/rector.php @@ -8,7 +8,6 @@ use Rector\CodeQuality\Rector\Ternary\SwitchNegatedTernaryRector; use Rector\Config\RectorConfig; use Rector\DeadCode\Rector\Cast\RecastingRemovalRector; -use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php70\Rector\FuncCall\RandomFunctionRector; use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector; @@ -20,6 +19,7 @@ use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\SetList; +use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; return RectorConfig::configure() ->withPaths([ diff --git a/src/Http/Adapter/FPM/Request.php b/src/Http/Adapter/FPM/Request.php index bb900f0..eda1dcd 100644 --- a/src/Http/Adapter/FPM/Request.php +++ b/src/Http/Adapter/FPM/Request.php @@ -66,11 +66,11 @@ public function getIP(): string } // Leftmost IP address is the address of the originating client - $ips = \explode(',', $headerValue); - $ip = \trim($ips[0]); + $ips = explode(',', $headerValue); + $ip = trim($ips[0]); // Validate IP format (supports both IPv4 and IPv6) - if (\filter_var($ip, FILTER_VALIDATE_IP)) { + if (filter_var($ip, FILTER_VALIDATE_IP)) { return $ip; } } @@ -97,7 +97,7 @@ public function getProtocol(): string */ public function getPort(): string { - return (string) \parse_url($this->getProtocol() . '://' . $this->getServer('HTTP_HOST', ''), PHP_URL_PORT); + return (string) parse_url($this->getProtocol() . '://' . $this->getServer('HTTP_HOST', ''), PHP_URL_PORT); } /** @@ -107,7 +107,7 @@ public function getPort(): string */ public function getHostname(): string { - $hostname = \parse_url($this->getProtocol() . '://' . $this->getServer('HTTP_HOST', ''), PHP_URL_HOST); + $hostname = parse_url($this->getProtocol() . '://' . $this->getServer('HTTP_HOST', ''), PHP_URL_HOST); return strtolower((string) ($hostname)); } @@ -233,7 +233,7 @@ public function getHeader(string $key, string $default = ''): string $value = $headers[$key]; - return \is_array($value) ? \implode(', ', $value) : $value; + return \is_array($value) ? implode(', ', $value) : $value; } /** @@ -278,14 +278,14 @@ protected function generateInput(): array $contentType = $this->getHeader('content-type'); // Get content-type without the charset - $length = \strpos($contentType, ';'); + $length = strpos($contentType, ';'); $length = (empty($length)) ? \strlen($contentType) : $length; - $contentType = \substr($contentType, 0, $length); + $contentType = substr($contentType, 0, $length); - $this->rawPayload = \file_get_contents('php://input') ?: ''; + $this->rawPayload = file_get_contents('php://input') ?: ''; $this->payload = match ($contentType) { - 'application/json' => \json_decode($this->rawPayload, true), + 'application/json' => json_decode($this->rawPayload, true), default => $_POST, }; @@ -323,7 +323,7 @@ protected function generateHeaders(): array foreach ($_SERVER as $name => $value) { if (str_starts_with($name, 'HTTP_')) { - $headers[\str_replace(' ', '-', \strtolower(\str_replace('_', ' ', \substr($name, 5))))] = $value; + $headers[str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5))))] = $value; } } diff --git a/src/Http/Adapter/FPM/Response.php b/src/Http/Adapter/FPM/Response.php index f0aaaa1..6a41a74 100644 --- a/src/Http/Adapter/FPM/Response.php +++ b/src/Http/Adapter/FPM/Response.php @@ -28,7 +28,7 @@ public function write(string $content): bool */ public function end(?string $content = null): void { - if (!is_null($content)) { + if (!\is_null($content)) { echo $content; } } @@ -53,10 +53,10 @@ public function sendHeader(string $key, mixed $value): void { if (\is_array($value)) { foreach ($value as $v) { - \header($key . ': ' . $v, false); + header($key . ': ' . $v, false); } } else { - \header($key . ': ' . $value); + header($key . ': ' . $value); } } @@ -74,6 +74,6 @@ protected function sendCookie(string $name, string $value, array $options): void unset($options['expire']); // Set the cookie - \setcookie($name, $value, $options); + setcookie($name, $value, $options); } } diff --git a/src/Http/Adapter/Swoole/Request.php b/src/Http/Adapter/Swoole/Request.php index e8ee638..5bf23bd 100644 --- a/src/Http/Adapter/Swoole/Request.php +++ b/src/Http/Adapter/Swoole/Request.php @@ -111,7 +111,7 @@ public function getProtocol(): string */ public function getPort(): string { - return $this->getHeader('x-forwarded-port', (string) \parse_url($this->getProtocol() . '://' . $this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_PORT)); + return $this->getHeader('x-forwarded-port', (string) parse_url($this->getProtocol() . '://' . $this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_PORT)); } /** @@ -121,8 +121,8 @@ public function getPort(): string */ public function getHostname(): string { - $hostname = \parse_url($this->getProtocol() . '://' . $this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_HOST); - return strtolower(strval($hostname)); + $hostname = parse_url($this->getProtocol() . '://' . $this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_HOST); + return strtolower(\strval($hostname)); } /** @@ -291,11 +291,11 @@ protected function generateInput(): array // Get content-type without the charset $length = strpos($contentType, ';'); - $length = (empty($length)) ? strlen($contentType) : $length; + $length = (empty($length)) ? \strlen($contentType) : $length; $contentType = substr($contentType, 0, $length); $this->payload = match ($contentType) { - 'application/json' => json_decode(strval($this->swoole->rawContent()), true), + 'application/json' => json_decode(\strval($this->swoole->rawContent()), true), default => $this->swoole->post, }; diff --git a/src/Http/Adapter/Swoole/Response.php b/src/Http/Adapter/Swoole/Response.php index d72615a..8676144 100644 --- a/src/Http/Adapter/Swoole/Response.php +++ b/src/Http/Adapter/Swoole/Response.php @@ -20,7 +20,7 @@ class Response extends UtopiaResponse public function __construct(SwooleResponse $response) { $this->swoole = $response; - parent::__construct(\microtime(true)); + parent::__construct(microtime(true)); } public function getSwooleResponse(): SwooleResponse diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 80fea42..b8cf4f1 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -3,16 +3,16 @@ namespace Utopia\Http\Adapter\Swoole; use Swoole\Coroutine; -use Utopia\Http\Adapter; -use Utopia\DI\Container; -use Swoole\Http\Server as SwooleServer; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; +use Swoole\Http\Server as SwooleServer; +use Utopia\DI\Container; +use Utopia\Http\Adapter; class Server extends Adapter { protected SwooleServer $server; - protected const REQUEST_CONTAINER_CONTEXT_KEY = '__utopia_http_request_container'; + protected const string REQUEST_CONTAINER_CONTEXT_KEY = '__utopia_http_request_container'; protected Container $container; /** diff --git a/src/Http/Adapter/SwooleCoroutine/Server.php b/src/Http/Adapter/SwooleCoroutine/Server.php index bb22a62..2b21ab1 100644 --- a/src/Http/Adapter/SwooleCoroutine/Server.php +++ b/src/Http/Adapter/SwooleCoroutine/Server.php @@ -3,15 +3,15 @@ namespace Utopia\Http\Adapter\SwooleCoroutine; use Swoole\Coroutine; -use Utopia\Http\Adapter; -use Utopia\DI\Container; use Swoole\Coroutine\Http\Server as SwooleServer; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; +use Utopia\DI\Container; +use Utopia\Http\Adapter; class Server extends Adapter { - protected const REQUEST_CONTAINER_CONTEXT_KEY = '__utopia_http_request_container'; + protected const string REQUEST_CONTAINER_CONTEXT_KEY = '__utopia_http_request_container'; protected SwooleServer $server; protected Container $container; diff --git a/src/Http/Files.php b/src/Http/Files.php index 0aee22b..37e27f3 100644 --- a/src/Http/Files.php +++ b/src/Http/Files.php @@ -21,7 +21,7 @@ class Files /** * @var array */ - public const EXTENSIONS = [ + public const array EXTENSIONS = [ 'css' => 'text/css', 'js' => 'text/javascript', 'svg' => 'image/svg+xml', @@ -79,7 +79,7 @@ public function load(string $directory, ?string $root = null): void $root ??= $directory; - $handle = opendir(strval($directory)); + $handle = opendir(\strval($directory)); if ($handle === false) { throw new Exception("Failed to open directory: {$directory}"); @@ -88,11 +88,11 @@ public function load(string $directory, ?string $root = null): void while ($path = readdir($handle)) { $extension = pathinfo($path, PATHINFO_EXTENSION); - if (in_array($path, ['.', '..'])) { + if (\in_array($path, ['.', '..'])) { continue; } - if (in_array($extension, ['php', 'phtml'])) { + if (\in_array($extension, ['php', 'phtml'])) { continue; } @@ -103,20 +103,20 @@ public function load(string $directory, ?string $root = null): void $dirPath = $directory . '/' . $path; if (is_dir($dirPath)) { - $this->load($dirPath, strval($root)); + $this->load($dirPath, \strval($root)); continue; } - $key = substr($dirPath, strlen(strval($root))); + $key = substr($dirPath, \strlen(\strval($root))); - if (array_key_exists($key, $this->loaded)) { + if (\array_key_exists($key, $this->loaded)) { continue; } $this->loaded[$key] = [ 'contents' => file_get_contents($dirPath), - 'mimeType' => (array_key_exists($extension, self::EXTENSIONS)) + 'mimeType' => (\array_key_exists($extension, self::EXTENSIONS)) ? self::EXTENSIONS[$extension] : mime_content_type($dirPath), ]; @@ -132,7 +132,7 @@ public function load(string $directory, ?string $root = null): void */ public function isFileLoaded(string $uri): bool { - return array_key_exists($uri, $this->loaded); + return \array_key_exists($uri, $this->loaded); } /** @@ -143,7 +143,7 @@ public function isFileLoaded(string $uri): bool */ public function getFileContents(string $uri): mixed { - if (!array_key_exists($uri, $this->loaded)) { + if (!\array_key_exists($uri, $this->loaded)) { throw new Exception('File not found or not loaded: ' . $uri); } @@ -158,7 +158,7 @@ public function getFileContents(string $uri): mixed */ public function getFileMimeType(string $uri): mixed { - if (!array_key_exists($uri, $this->loaded)) { + if (!\array_key_exists($uri, $this->loaded)) { throw new Exception('File not found or not loaded: ' . $uri); } diff --git a/src/Http/Http.php b/src/Http/Http.php index da93d66..74965fc 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -14,35 +14,35 @@ class Http { - public const COMPRESSION_MIN_SIZE_DEFAULT = 1024; - public const COMPRESSION_BROTLI_LEVEL_DEFAULT = 4; - public const COMPRESSION_ZSTD_LEVEL_DEFAULT = 3; + public const int COMPRESSION_MIN_SIZE_DEFAULT = 1024; + public const int COMPRESSION_BROTLI_LEVEL_DEFAULT = 4; + public const int COMPRESSION_ZSTD_LEVEL_DEFAULT = 3; /** * Request method constants */ - public const REQUEST_METHOD_GET = 'GET'; + public const string REQUEST_METHOD_GET = 'GET'; - public const REQUEST_METHOD_POST = 'POST'; + public const string REQUEST_METHOD_POST = 'POST'; - public const REQUEST_METHOD_PUT = 'PUT'; + public const string REQUEST_METHOD_PUT = 'PUT'; - public const REQUEST_METHOD_PATCH = 'PATCH'; + public const string REQUEST_METHOD_PATCH = 'PATCH'; - public const REQUEST_METHOD_DELETE = 'DELETE'; + public const string REQUEST_METHOD_DELETE = 'DELETE'; - public const REQUEST_METHOD_OPTIONS = 'OPTIONS'; + public const string REQUEST_METHOD_OPTIONS = 'OPTIONS'; - public const REQUEST_METHOD_HEAD = 'HEAD'; + public const string REQUEST_METHOD_HEAD = 'HEAD'; /** * Mode Type */ - public const MODE_TYPE_DEVELOPMENT = 'development'; + public const string MODE_TYPE_DEVELOPMENT = 'development'; - public const MODE_TYPE_STAGE = 'stage'; + public const string MODE_TYPE_STAGE = 'stage'; - public const MODE_TYPE_PRODUCTION = 'production'; + public const string MODE_TYPE_PRODUCTION = 'production'; protected Files $files; @@ -142,7 +142,7 @@ class Http */ public function __construct(Adapter $server, string $timezone) { - \date_default_timezone_set($timezone); + date_default_timezone_set($timezone); $this->files = new Files(); $this->server = $server; $this->container = $server->getContainer(); @@ -375,9 +375,9 @@ public function getResource(string $name): mixed return $this->server->getContainer()->get($name); } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { // Normalize DI container errors to the Http layer's "resource" terminology. - $message = \str_replace('dependency', 'resource', $e->getMessage()); + $message = str_replace('dependency', 'resource', $e->getMessage()); - if ($message === $e->getMessage() && !\str_contains($message, 'resource')) { + if ($message === $e->getMessage() && !str_contains($message, 'resource')) { $message = 'Failed to find resource: "' . $name . '"'; } @@ -566,7 +566,7 @@ public function start(): void $this->setResource('error', fn() => $e); foreach (self::$errors as $error) { // Global error hooks - if (in_array('*', $error->getGroups())) { + if (\in_array('*', $error->getGroups())) { try { $arguments = $this->getArguments($error, [], []); \call_user_func_array($error->getAction(), $arguments); @@ -594,7 +594,7 @@ public function match(Request $request, bool $fresh = true): ?Route return $this->route; } - $url = \parse_url($request->getURI(), PHP_URL_PATH); + $url = parse_url($request->getURI(), PHP_URL_PATH); $url = \is_string($url) ? ($url === '' ? '/' : $url) : '/'; $method = $request->getMethod(); $method = (self::REQUEST_METHOD_HEAD === $method) ? self::REQUEST_METHOD_GET : $method; @@ -618,7 +618,7 @@ public function execute(Route $route, Request $request, Response $response): sta try { if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks - if (in_array('*', $hook->getGroups())) { + if (\in_array('*', $hook->getGroups())) { $arguments = $this->getArguments($hook, $pathValues, $request->getParams()); \call_user_func_array($hook->getAction(), $arguments); } @@ -705,7 +705,7 @@ protected function getArguments(Hook $hook, array $values, array $requestParams) $arg = $existsInRequest ? $requestParams[$key] : $param['default']; if (\is_callable($arg) && !\is_string($arg)) { - $arg = \call_user_func_array($arg, \array_values($this->getResources($param['injections']))); + $arg = \call_user_func_array($arg, array_values($this->getResources($param['injections']))); } $value = $existsInValues ? $values[$key] : $arg; @@ -806,7 +806,7 @@ private function runInternal(Request $request, Response $response): static $response ->setContentType($this->getFileMimeType($request->getURI())) ->addHeader('Cache-Control', 'public, max-age=' . $time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache + ->addHeader('Expires', date('D, d M Y H:i:s', time() + $time) . ' GMT') // 45 days cache ->send($this->getFileContents($request->getURI())); return $this; @@ -856,7 +856,7 @@ private function runInternal(Request $request, Response $response): static if (null === $route && null !== self::$wildcardRoute) { $route = self::$wildcardRoute; $this->route = $route; - $path = \parse_url($request->getURI(), PHP_URL_PATH); + $path = parse_url($request->getURI(), PHP_URL_PATH); $path = \is_string($path) ? ($path === '' ? '/' : $path) : '/'; $route->path($path); @@ -920,7 +920,7 @@ protected function validate(string $key, array $param, mixed $value): void $validator = $param['validator']; // checking whether the class exists if (\is_callable($validator)) { - $validator = \call_user_func_array($validator, \array_values($this->getResources($param['injections']))); + $validator = \call_user_func_array($validator, array_values($this->getResources($param['injections']))); } if (!$validator instanceof Validator) { // is the validator object an instance of the Validator class diff --git a/src/Http/Request.php b/src/Http/Request.php index b8618bb..7042de6 100755 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -7,23 +7,23 @@ abstract class Request /** * HTTP methods */ - public const METHOD_OPTIONS = 'OPTIONS'; + public const string METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_GET = 'GET'; + public const string METHOD_GET = 'GET'; - public const METHOD_HEAD = 'HEAD'; + public const string METHOD_HEAD = 'HEAD'; - public const METHOD_POST = 'POST'; + public const string METHOD_POST = 'POST'; - public const METHOD_PATCH = 'PATCH'; + public const string METHOD_PATCH = 'PATCH'; - public const METHOD_PUT = 'PUT'; + public const string METHOD_PUT = 'PUT'; - public const METHOD_DELETE = 'DELETE'; + public const string METHOD_DELETE = 'DELETE'; - public const METHOD_TRACE = 'TRACE'; + public const string METHOD_TRACE = 'TRACE'; - public const METHOD_CONNECT = 'CONNECT'; + public const string METHOD_CONNECT = 'CONNECT'; /** * Container for php://input parsed stream as an associative array @@ -130,9 +130,9 @@ abstract public function setServer(string $key, string $value): static; */ public function setTrustedIpHeaders(array $headers): static { - $normalized = \array_map(strtolower(...), $headers); - $trimmed = \array_map(trim(...), $normalized); - $this->trustedIpHeaders = \array_filter($trimmed); + $normalized = array_map(strtolower(...), $headers); + $trimmed = array_map(trim(...), $normalized); + $this->trustedIpHeaders = array_filter($trimmed); return $this; } @@ -287,9 +287,9 @@ public function getSize(): int $headers = $this->generateHeaders(); $headerStrings = []; foreach ($headers as $key => $value) { - $headerStrings[] = \is_array($value) ? $key . ': ' . \implode(', ', $value) : $key . ': ' . $value; + $headerStrings[] = \is_array($value) ? $key . ': ' . implode(', ', $value) : $key . ': ' . $value; } - return \mb_strlen(\implode("\n", $headerStrings), '8bit') + \mb_strlen(\file_get_contents('php://input') ?: '', '8bit'); + return mb_strlen(implode("\n", $headerStrings), '8bit') + mb_strlen(file_get_contents('php://input') ?: '', '8bit'); } /** @@ -436,7 +436,7 @@ protected function generateHeaders(): array foreach ($_SERVER as $name => $value) { if (str_starts_with($name, 'HTTP_')) { - $headers[\str_replace(' ', '-', \strtolower(\str_replace('_', ' ', \substr($name, 5))))] = $value; + $headers[str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5))))] = $value; } } @@ -473,7 +473,7 @@ protected function parseContentRange(): ?array $data = []; if (!empty($contentRange)) { $contentRange = explode(' ', $contentRange); - if (count($contentRange) !== 2) { + if (\count($contentRange) !== 2) { return null; } @@ -484,7 +484,7 @@ protected function parseContentRange(): ?array } $rangeData = explode('/', $contentRange[1]); - if (count($rangeData) !== 2) { + if (\count($rangeData) !== 2) { return null; } @@ -494,7 +494,7 @@ protected function parseContentRange(): ?array $data['size'] = (int) $rangeData[1]; $parts = explode('-', $rangeData[0]); - if (count($parts) !== 2) { + if (\count($parts) !== 2) { return null; } @@ -530,13 +530,13 @@ protected function parseRange(): ?array $data = []; $ranges = explode('=', $rangeHeader); - if (count($ranges) !== 2 || empty($ranges[0]) || empty($ranges[1])) { + if (\count($ranges) !== 2 || empty($ranges[0]) || empty($ranges[1])) { return null; } $data['unit'] = $ranges[0]; $ranges = explode('-', $ranges[1]); - if (count($ranges) !== 2 || $ranges[0] === '') { + if (\count($ranges) !== 2 || $ranges[0] === '') { return null; } diff --git a/src/Http/Response.php b/src/Http/Response.php index cf3dac6..fde5d6b 100755 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -11,107 +11,107 @@ abstract class Response /** * HTTP content types */ - public const CONTENT_TYPE_TEXT = 'text/plain'; + public const string CONTENT_TYPE_TEXT = 'text/plain'; - public const CONTENT_TYPE_HTML = 'text/html'; + public const string CONTENT_TYPE_HTML = 'text/html'; - public const CONTENT_TYPE_JSON = 'application/json'; + public const string CONTENT_TYPE_JSON = 'application/json'; - public const CONTENT_TYPE_XML = 'text/xml'; + public const string CONTENT_TYPE_XML = 'text/xml'; - public const CONTENT_TYPE_JAVASCRIPT = 'text/javascript'; + public const string CONTENT_TYPE_JAVASCRIPT = 'text/javascript'; - public const CONTENT_TYPE_IMAGE = 'image/*'; + public const string CONTENT_TYPE_IMAGE = 'image/*'; - public const CONTENT_TYPE_IMAGE_JPEG = 'image/jpeg'; + public const string CONTENT_TYPE_IMAGE_JPEG = 'image/jpeg'; - public const CONTENT_TYPE_IMAGE_PNG = 'image/png'; + public const string CONTENT_TYPE_IMAGE_PNG = 'image/png'; - public const CONTENT_TYPE_IMAGE_GIF = 'image/gif'; + public const string CONTENT_TYPE_IMAGE_GIF = 'image/gif'; - public const CONTENT_TYPE_IMAGE_SVG = 'image/svg+xml'; + public const string CONTENT_TYPE_IMAGE_SVG = 'image/svg+xml'; - public const CONTENT_TYPE_IMAGE_WEBP = 'image/webp'; + public const string CONTENT_TYPE_IMAGE_WEBP = 'image/webp'; - public const CONTENT_TYPE_IMAGE_ICON = 'image/x-icon'; + public const string CONTENT_TYPE_IMAGE_ICON = 'image/x-icon'; - public const CONTENT_TYPE_IMAGE_BMP = 'image/bmp'; + public const string CONTENT_TYPE_IMAGE_BMP = 'image/bmp'; /** * Chrsets */ - public const CHARSET_UTF8 = 'UTF-8'; + public const string CHARSET_UTF8 = 'UTF-8'; /** * HTTP response status codes */ - public const STATUS_CODE_CONTINUE = 100; - public const STATUS_CODE_SWITCHING_PROTOCOLS = 101; - public const STATUS_CODE_PROCESSING = 102; - public const STATUS_CODE_EARLY_HINTS = 103; - - public const STATUS_CODE_OK = 200; - public const STATUS_CODE_CREATED = 201; - public const STATUS_CODE_ACCEPTED = 202; - public const STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203; - public const STATUS_CODE_NOCONTENT = 204; - public const STATUS_CODE_RESETCONTENT = 205; - public const STATUS_CODE_PARTIALCONTENT = 206; - public const STATUS_CODE_MULTI_STATUS = 207; - public const STATUS_CODE_ALREADY_REPORTED = 208; - public const STATUS_CODE_IM_USED = 226; - - public const STATUS_CODE_MULTIPLE_CHOICES = 300; - public const STATUS_CODE_MOVED_PERMANENTLY = 301; - public const STATUS_CODE_FOUND = 302; - public const STATUS_CODE_SEE_OTHER = 303; - public const STATUS_CODE_NOT_MODIFIED = 304; - public const STATUS_CODE_USE_PROXY = 305; - public const STATUS_CODE_UNUSED = 306; - public const STATUS_CODE_TEMPORARY_REDIRECT = 307; - public const STATUS_CODE_PERMANENT_REDIRECT = 308; - - public const STATUS_CODE_BAD_REQUEST = 400; - public const STATUS_CODE_UNAUTHORIZED = 401; - public const STATUS_CODE_PAYMENT_REQUIRED = 402; - public const STATUS_CODE_FORBIDDEN = 403; - public const STATUS_CODE_NOT_FOUND = 404; - public const STATUS_CODE_METHOD_NOT_ALLOWED = 405; - public const STATUS_CODE_NOT_ACCEPTABLE = 406; - public const STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407; - public const STATUS_CODE_REQUEST_TIMEOUT = 408; - public const STATUS_CODE_CONFLICT = 409; - public const STATUS_CODE_GONE = 410; - public const STATUS_CODE_LENGTH_REQUIRED = 411; - public const STATUS_CODE_PRECONDITION_FAILED = 412; - public const STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413; - public const STATUS_CODE_REQUEST_URI_TOO_LONG = 414; - public const STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415; - public const STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - public const STATUS_CODE_EXPECTATION_FAILED = 417; - public const STATUS_CODE_IM_A_TEAPOT = 418; - public const STATUS_CODE_MISDIRECTED_REQUEST = 421; - public const STATUS_CODE_UNPROCESSABLE_ENTITY = 422; - public const STATUS_CODE_LOCKED = 423; - public const STATUS_CODE_FAILED_DEPENDENCY = 424; - public const STATUS_CODE_TOO_EARLY = 425; - public const STATUS_CODE_UPGRADE_REQUIRED = 426; - public const STATUS_CODE_PRECONDITION_REQUIRED = 428; - public const STATUS_CODE_TOO_MANY_REQUESTS = 429; - public const STATUS_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; - public const STATUS_CODE_UNAVAILABLE_FOR_LEGAL_REASONS = 451; - - public const STATUS_CODE_INTERNAL_SERVER_ERROR = 500; - public const STATUS_CODE_NOT_IMPLEMENTED = 501; - public const STATUS_CODE_BAD_GATEWAY = 502; - public const STATUS_CODE_SERVICE_UNAVAILABLE = 503; - public const STATUS_CODE_GATEWAY_TIMEOUT = 504; - public const STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505; - public const STATUS_CODE_VARIANT_ALSO_NEGOTIATES = 506; - public const STATUS_CODE_INSUFFICIENT_STORAGE = 507; - public const STATUS_CODE_LOOP_DETECTED = 508; - public const STATUS_CODE_NOT_EXTENDED = 510; - public const STATUS_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511; + public const int STATUS_CODE_CONTINUE = 100; + public const int STATUS_CODE_SWITCHING_PROTOCOLS = 101; + public const int STATUS_CODE_PROCESSING = 102; + public const int STATUS_CODE_EARLY_HINTS = 103; + + public const int STATUS_CODE_OK = 200; + public const int STATUS_CODE_CREATED = 201; + public const int STATUS_CODE_ACCEPTED = 202; + public const int STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203; + public const int STATUS_CODE_NOCONTENT = 204; + public const int STATUS_CODE_RESETCONTENT = 205; + public const int STATUS_CODE_PARTIALCONTENT = 206; + public const int STATUS_CODE_MULTI_STATUS = 207; + public const int STATUS_CODE_ALREADY_REPORTED = 208; + public const int STATUS_CODE_IM_USED = 226; + + public const int STATUS_CODE_MULTIPLE_CHOICES = 300; + public const int STATUS_CODE_MOVED_PERMANENTLY = 301; + public const int STATUS_CODE_FOUND = 302; + public const int STATUS_CODE_SEE_OTHER = 303; + public const int STATUS_CODE_NOT_MODIFIED = 304; + public const int STATUS_CODE_USE_PROXY = 305; + public const int STATUS_CODE_UNUSED = 306; + public const int STATUS_CODE_TEMPORARY_REDIRECT = 307; + public const int STATUS_CODE_PERMANENT_REDIRECT = 308; + + public const int STATUS_CODE_BAD_REQUEST = 400; + public const int STATUS_CODE_UNAUTHORIZED = 401; + public const int STATUS_CODE_PAYMENT_REQUIRED = 402; + public const int STATUS_CODE_FORBIDDEN = 403; + public const int STATUS_CODE_NOT_FOUND = 404; + public const int STATUS_CODE_METHOD_NOT_ALLOWED = 405; + public const int STATUS_CODE_NOT_ACCEPTABLE = 406; + public const int STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407; + public const int STATUS_CODE_REQUEST_TIMEOUT = 408; + public const int STATUS_CODE_CONFLICT = 409; + public const int STATUS_CODE_GONE = 410; + public const int STATUS_CODE_LENGTH_REQUIRED = 411; + public const int STATUS_CODE_PRECONDITION_FAILED = 412; + public const int STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413; + public const int STATUS_CODE_REQUEST_URI_TOO_LONG = 414; + public const int STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415; + public const int STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + public const int STATUS_CODE_EXPECTATION_FAILED = 417; + public const int STATUS_CODE_IM_A_TEAPOT = 418; + public const int STATUS_CODE_MISDIRECTED_REQUEST = 421; + public const int STATUS_CODE_UNPROCESSABLE_ENTITY = 422; + public const int STATUS_CODE_LOCKED = 423; + public const int STATUS_CODE_FAILED_DEPENDENCY = 424; + public const int STATUS_CODE_TOO_EARLY = 425; + public const int STATUS_CODE_UPGRADE_REQUIRED = 426; + public const int STATUS_CODE_PRECONDITION_REQUIRED = 428; + public const int STATUS_CODE_TOO_MANY_REQUESTS = 429; + public const int STATUS_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; + public const int STATUS_CODE_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + + public const int STATUS_CODE_INTERNAL_SERVER_ERROR = 500; + public const int STATUS_CODE_NOT_IMPLEMENTED = 501; + public const int STATUS_CODE_BAD_GATEWAY = 502; + public const int STATUS_CODE_SERVICE_UNAVAILABLE = 503; + public const int STATUS_CODE_GATEWAY_TIMEOUT = 504; + public const int STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505; + public const int STATUS_CODE_VARIANT_ALSO_NEGOTIATES = 506; + public const int STATUS_CODE_INSUFFICIENT_STORAGE = 507; + public const int STATUS_CODE_LOOP_DETECTED = 508; + public const int STATUS_CODE_NOT_EXTENDED = 510; + public const int STATUS_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511; /** * @var array @@ -254,13 +254,13 @@ abstract class Response 'application/javascript-binast' => true, ]; - public const COOKIE_SAMESITE_NONE = 'None'; + public const string COOKIE_SAMESITE_NONE = 'None'; - public const COOKIE_SAMESITE_STRICT = 'Strict'; + public const string COOKIE_SAMESITE_STRICT = 'Strict'; - public const COOKIE_SAMESITE_LAX = 'Lax'; + public const string COOKIE_SAMESITE_LAX = 'Lax'; - public const CHUNK_SIZE = 2000000; //2mb + public const int CHUNK_SIZE = 2000000; //2mb protected int $statusCode = self::STATUS_CODE_OK; protected string $contentType = ''; @@ -298,7 +298,7 @@ abstract class Response */ public function __construct(float $time = 0) { - $this->startTime = (!empty($time)) ? $time : \microtime(true); + $this->startTime = (!empty($time)) ? $time : microtime(true); } private function isCompressible(?string $contentType): bool @@ -544,7 +544,7 @@ public function send(string $body = ''): void $hasContentEncoding = false; foreach ($this->headers as $name => $values) { - if (\strtolower($name) === 'content-encoding') { + if (strtolower($name) === 'content-encoding') { $hasContentEncoding = true; break; } @@ -555,7 +555,7 @@ public function send(string $body = ''): void !$hasContentEncoding && !empty($this->acceptEncoding) && $this->isCompressible($this->contentType) - && strlen($body) > $this->compressionMinSize + && \strlen($body) > $this->compressionMinSize ) { $algorithm = Compression::fromAcceptEncoding($this->acceptEncoding, $this->compressionSupported); @@ -599,7 +599,7 @@ public function send(string $body = ''): void } $headersSize += (\count($this->headers) - 1) * 2; // linebreaks - $bodyLength = strlen($body); + $bodyLength = \strlen($body); $this->size += $headersSize + $bodyLength; if ($bodyLength <= self::CHUNK_SIZE) { @@ -759,7 +759,7 @@ protected function appendCookies(): static public function redirect(string $url, int $statusCode = 301): void { if (300 === $statusCode) { - \trigger_error('It seems webkit based browsers have problems redirecting link with 300 status codes!', E_USER_NOTICE); + trigger_error('It seems webkit based browsers have problems redirecting link with 300 status codes!', E_USER_NOTICE); } $this @@ -808,13 +808,13 @@ public function text(string $data): void */ public function json($data): void { - if (!is_array($data) && !$data instanceof \stdClass) { + if (!\is_array($data) && !$data instanceof \stdClass) { throw new \Exception('Invalid JSON input var'); } $this ->setContentType(Response::CONTENT_TYPE_JSON, self::CHARSET_UTF8) - ->send(\json_encode($data, JSON_UNESCAPED_UNICODE) ?: ''); + ->send(json_encode($data, JSON_UNESCAPED_UNICODE) ?: ''); } /** @@ -831,7 +831,7 @@ public function jsonp(string $callback, array $data): void { $this ->setContentType(self::CONTENT_TYPE_JAVASCRIPT, self::CHARSET_UTF8) - ->send('parent.' . $callback . '(' . \json_encode($data) . ');'); + ->send('parent.' . $callback . '(' . json_encode($data) . ');'); } /** @@ -846,7 +846,7 @@ public function iframe(string $callback, array $data): void { $this ->setContentType(self::CONTENT_TYPE_HTML, self::CHARSET_UTF8) - ->send(''); + ->send(''); } /** diff --git a/src/Http/Route.php b/src/Http/Route.php index 46bfb29..b72886d 100755 --- a/src/Http/Route.php +++ b/src/Http/Route.php @@ -140,13 +140,13 @@ public function getPathValues(Request $request, string $path = ''): array $parts = explode('/', ltrim($request->getURI(), '/')); if (empty($path)) { - $pathParams = $this->pathParams[$path] ?? \array_values($this->pathParams)[0] ?? []; + $pathParams = $this->pathParams[$path] ?? array_values($this->pathParams)[0] ?? []; } else { $pathParams = $this->pathParams[$path] ?? []; } foreach ($pathParams as $key => $index) { - if (array_key_exists($index, $parts)) { + if (\array_key_exists($index, $parts)) { $pathValues[$key] = $parts[$index]; } } diff --git a/src/Http/Router.php b/src/Http/Router.php index 45fde18..8118ffe 100644 --- a/src/Http/Router.php +++ b/src/Http/Router.php @@ -9,8 +9,8 @@ class Router /** * Placeholder token for params in paths. */ - public const PLACEHOLDER_TOKEN = ':::'; - public const WILDCARD_TOKEN = '*'; + public const string PLACEHOLDER_TOKEN = ':::'; + public const string WILDCARD_TOKEN = '*'; protected static bool $allowOverride = false; @@ -70,11 +70,11 @@ public static function addRoute(Route $route): void { [$path, $params] = self::preparePath($route->getPath()); - if (!array_key_exists($route->getMethod(), self::$routes)) { + if (!\array_key_exists($route->getMethod(), self::$routes)) { throw new Exception("Method ({$route->getMethod()}) not supported."); } - if (array_key_exists($path, self::$routes[$route->getMethod()]) && !self::$allowOverride) { + if (\array_key_exists($path, self::$routes[$route->getMethod()]) && !self::$allowOverride) { throw new Exception("Route for ({$route->getMethod()}:{$path}) already registered."); } @@ -94,7 +94,7 @@ public static function addRouteAlias(string $path, Route $route): void { [$alias, $params] = self::preparePath($path); - if (array_key_exists($alias, self::$routes[$route->getMethod()]) && !self::$allowOverride) { + if (\array_key_exists($alias, self::$routes[$route->getMethod()]) && !self::$allowOverride) { throw new Exception("Route for ({$route->getMethod()}:{$alias}) already registered."); } @@ -110,12 +110,12 @@ public static function addRouteAlias(string $path, Route $route): void */ public static function match(string $method, string $path): ?Route { - if (!array_key_exists($method, self::$routes)) { + if (!\array_key_exists($method, self::$routes)) { return null; } $parts = array_values(array_filter(explode('/', $path), fn($segment) => $segment !== '')); - $length = count($parts) - 1; + $length = \count($parts) - 1; $filteredParams = array_filter(self::$params, fn($i) => $i <= $length); foreach (self::combinations($filteredParams) as $sample) { @@ -128,7 +128,7 @@ public static function match(string $method, string $path): ?Route ), ); - if (array_key_exists($match, self::$routes[$method])) { + if (\array_key_exists($match, self::$routes[$method])) { $route = self::$routes[$method][$match]; $route->setMatchedPath($match); return $route; @@ -139,7 +139,7 @@ public static function match(string $method, string $path): ?Route * Match root wildcard. */ $match = self::WILDCARD_TOKEN; - if (array_key_exists($match, self::$routes[$method])) { + if (\array_key_exists($match, self::$routes[$method])) { $route = self::$routes[$method][$match]; $route->setMatchedPath($match); return $route; @@ -151,7 +151,7 @@ public static function match(string $method, string $path): ?Route foreach ($parts as $part) { $current = ($current ?? '') . "{$part}/"; $match = $current . self::WILDCARD_TOKEN; - if (array_key_exists($match, self::$routes[$method])) { + if (\array_key_exists($match, self::$routes[$method])) { $route = self::$routes[$method][$match]; $route->setMatchedPath($match); return $route; @@ -202,7 +202,7 @@ public static function preparePath(string $path): array if (str_starts_with($part, ':')) { $prepare .= self::PLACEHOLDER_TOKEN; $params[ltrim($part, ':')] = $key; - if (!in_array($key, self::$params)) { + if (!\in_array($key, self::$params)) { self::$params[] = $key; } } else { diff --git a/src/Http/View.php b/src/Http/View.php index a2d1705..32161c7 100644 --- a/src/Http/View.php +++ b/src/Http/View.php @@ -6,9 +6,9 @@ class View { - public const FILTER_ESCAPE = 'escape'; + public const string FILTER_ESCAPE = 'escape'; - public const FILTER_NL2P = 'nl2p'; + public const string FILTER_NL2P = 'nl2p'; /** * @var self|null @@ -42,17 +42,17 @@ public function __construct(string $path = '') $this->setPath($path); $this - ->addFilter(self::FILTER_ESCAPE, fn(string $value) => \htmlentities($value, ENT_QUOTES, 'UTF-8')) + ->addFilter(self::FILTER_ESCAPE, fn(string $value) => htmlentities($value, ENT_QUOTES, 'UTF-8')) ->addFilter(self::FILTER_NL2P, function (string $value) { $paragraphs = ''; - foreach (\explode("\n\n", $value) as $line) { - if (\trim($line)) { + foreach (explode("\n\n", $value) as $line) { + if (trim($line)) { $paragraphs .= '

' . $line . '

'; } } - return \str_replace("\n", '
', $paragraphs); + return str_replace("\n", '
', $paragraphs); }); } @@ -70,8 +70,8 @@ public function setParam(string $key, mixed $value, bool $escapeHtml = true): st throw new Exception('$key can\'t contain a dot "." character'); } - if (is_string($value) && $escapeHtml) { - $value = \htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); + if (\is_string($value) && $escapeHtml) { + $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); } $this->params[$key] = $value; @@ -112,7 +112,7 @@ public function getParent(): ?self */ public function getParam(string $path, mixed $default = null): mixed { - $path = \explode('.', $path); + $path = explode('.', $path); $temp = $this->params; foreach ($path as $key) { @@ -220,9 +220,9 @@ public function render(bool $minify = true): string return ''; } - \ob_start(); //Start of build + ob_start(); //Start of build - if (\is_readable($this->path)) { + if (is_readable($this->path)) { /** * Include template file * @@ -230,22 +230,22 @@ public function render(bool $minify = true): string */ include $this->path; } else { - \ob_end_clean(); + ob_end_clean(); throw new Exception('"' . $this->path . '" view template is not readable'); } - $html = \ob_get_contents() ?: ''; + $html = ob_get_contents() ?: ''; - \ob_end_clean(); //End of build + ob_end_clean(); //End of build if ($minify) { // Searching textarea and pre - \preg_match_all('#\.*\<\/textarea\>#Uis', $html, $foundTxt); - \preg_match_all('#\.*\<\/pre\>#Uis', $html, $foundPre); + preg_match_all('#\.*\<\/textarea\>#Uis', $html, $foundTxt); + preg_match_all('#\.*\<\/pre\>#Uis', $html, $foundPre); // replacing both with /
$index
- $html = \str_replace($foundTxt[0], \array_map(fn($el) => '', \array_keys($foundTxt[0])), $html); - $html = \str_replace($foundPre[0], \array_map(fn($el) => '
' . $el . '
', \array_keys($foundPre[0])), $html); + $html = str_replace($foundTxt[0], array_map(fn($el) => '', array_keys($foundTxt[0])), $html); + $html = str_replace($foundPre[0], array_map(fn($el) => '
' . $el . '
', array_keys($foundPre[0])), $html); // your stuff $search = [ @@ -260,11 +260,11 @@ public function render(bool $minify = true): string '\\1', ]; - $html = \preg_replace($search, $replace, $html) ?? $html; + $html = preg_replace($search, $replace, $html) ?? $html; // Replacing back with content - $html = \str_replace(\array_map(fn($el) => '', \array_keys($foundTxt[0])), $foundTxt[0], $html); - $html = \str_replace(\array_map(fn($el) => '
' . $el . '
', \array_keys($foundPre[0])), $foundPre[0], $html); + $html = str_replace(array_map(fn($el) => '', array_keys($foundTxt[0])), $foundTxt[0], $html); + $html = str_replace(array_map(fn($el) => '
' . $el . '
', array_keys($foundPre[0])), $foundPre[0], $html); } return $html; diff --git a/tests/HttpTest.php b/tests/HttpTest.php index dbb703c..6535df0 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -7,11 +7,11 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Utopia\DI\Container; -use Utopia\Http\Tests\UtopiaFPMRequestTest; -use Utopia\Validator\Text; use Utopia\Http\Adapter\FPM\Request; use Utopia\Http\Adapter\FPM\Response; use Utopia\Http\Adapter\FPM\Server; +use Utopia\Http\Tests\UtopiaFPMRequestTest; +use Utopia\Validator\Text; final class HttpTest extends TestCase { @@ -110,10 +110,10 @@ public function testCanExecuteRoute(): void echo $x . '-' . $y; }); - \ob_start(); + ob_start(); $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); // With Params $resource = $this->container->get('rand'); @@ -132,12 +132,12 @@ public function testCanExecuteRoute(): void echo $x . '-', $y; }); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); $this->http->execute($route, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame($resource . '-param-x-param-y', $result); @@ -152,12 +152,12 @@ public function testCanExecuteRoute(): void echo $x . '-', $y; }); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); $this->http->execute($route, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); @@ -224,22 +224,22 @@ public function testCanExecuteRoute(): void echo $x . '*', $y; }); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); $this->http->execute($route, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); $resource = $this->container->get('rand'); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); $this->http->execute($homepage, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('init-' . $resource . '-(init-homepage)-param-x*param-y-(shutdown-homepage)-shutdown', $result); } @@ -266,10 +266,10 @@ public function testCanAddAndExecuteHooks(): void echo $x; }); - \ob_start(); + ob_start(); $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('(init)-x-def-(shutdown)', $result); @@ -282,10 +282,10 @@ public function testCanAddAndExecuteHooks(): void echo $x; }); - \ob_start(); + ob_start(); $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('x-def', $result); } @@ -350,18 +350,18 @@ public function testCanHookThrowExceptions(): void echo $x; }); - \ob_start(); + ob_start(); $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('error-Param "y" is not optional.', $result); - \ob_start(); + ob_start(); $_GET['y'] = 'y-def'; $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('(init)-y-def-x-def-(shutdown)', $result); } @@ -512,10 +512,10 @@ public function testCanRunRequest(): void $response->send('HELLO'); }); - \ob_start(); + ob_start(); $this->http->run(new Request(), new Response()); - $result = \ob_get_contents() ?: ''; - \ob_end_clean(); + $result = ob_get_contents() ?: ''; + ob_end_clean(); $_SERVER['REQUEST_METHOD'] = $method; $_SERVER['REQUEST_URI'] = $uri; @@ -549,19 +549,19 @@ public function testWildcardRoute(): void } }); - \ob_start(); + ob_start(); @$this->http->run(new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('HELLO', $result); - \ob_start(); + ob_start(); $req = new Request(); $req = $req->setMethod('OPTIONS'); @$this->http->run($req, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('', $result); @@ -583,10 +583,10 @@ public function testWildcardRouteWhenUriHasNoPath(): void $response->send('HELLO'); }); - \ob_start(); + ob_start(); @$this->http->run(new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $_SERVER['REQUEST_METHOD'] = $method; $_SERVER['REQUEST_URI'] = $uri; @@ -607,10 +607,10 @@ public function testCallableStringParametersNotExecuted(): void echo 'callback-value: ' . $callback; }); - \ob_start(); + ob_start(); $this->http->execute($route, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('callback-value: phpinfo', $result); @@ -623,12 +623,12 @@ public function testCallableStringParametersNotExecuted(): void echo 'func-value: ' . $func; }); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['func' => 'system']); $this->http->execute($route2, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('func-value: system', $result); @@ -641,10 +641,10 @@ public function testCallableStringParametersNotExecuted(): void echo 'generated: ' . $generated; }); - \ob_start(); + ob_start(); $this->http->execute($route3, new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); $this->assertSame('generated: generated-value', $result); } @@ -661,20 +661,20 @@ public function testCanInjectResourceAndParamWithSameName(): void ->param('locale', 'en-default', new Text(10), 'locale param', false) ->inject('locale') ->action(function (string $localeParam, Locale $localeResource) { - echo \json_encode([ + echo json_encode([ 'localeParam' => $localeParam, 'localeResource' => $localeResource->name, ]); }); - \ob_start(); + ob_start(); $request = new UtopiaFPMRequestTest(); $request::_setParams(['locale' => 'es']); $this->http->execute($route, $request, new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); + $result = ob_get_contents(); + ob_end_clean(); - $expected = \json_encode([ + $expected = json_encode([ 'localeParam' => 'es', 'localeResource' => 'en', ]); diff --git a/tests/UtopiaFPMRequestTest.php b/tests/UtopiaFPMRequestTest.php index b2c4d40..b45dbfc 100644 --- a/tests/UtopiaFPMRequestTest.php +++ b/tests/UtopiaFPMRequestTest.php @@ -44,7 +44,7 @@ public function getParams(): array $paramsArray = $this::_getParams(); } - return \array_merge($paramsArray, parent::getParams()); + return array_merge($paramsArray, parent::getParams()); } /** diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index 82c1468..69516d5 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -72,10 +72,10 @@ public function call(string $method, string $path = '', array $headers = [], arr curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders, &$cookies) { - $len = strlen($header); + $len = \strlen($header); $header = explode(':', $header, 2); - if (count($header) < 2) { // ignore invalid headers + if (\count($header) < 2) { // ignore invalid headers return $len; }