From 5db6b13f4a8bee44ad1e3be7f16c44b322795d60 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 4 Apr 2024 17:19:28 +0200 Subject: [PATCH 01/71] Work in progress --- README.md | 32 +- composer.json | 11 +- composer.lock | 176 +++-- docs/Getting-Starting-Guide.md | 8 +- example/src/server.php | 2 +- src/Http/Adapter/FPM/Server.php | 3 - src/Http/Adapter/Swoole/Server.php | 7 +- src/Http/Hook.php | 50 +- src/Http/Http.php | 395 ++++------ src/Http/Route.php | 2 - tests/HookTest.php | 150 ++-- tests/HttpTest.php | 1160 +++++++++++++--------------- tests/RouteTest.php | 18 +- tests/e2e/BaseTest.php | 60 +- tests/e2e/ResponseFPMTest.php | 24 +- tests/e2e/ResponseSwooleTest.php | 34 +- tests/e2e/init.php | 10 +- tests/e2e/server-fpm.php | 3 +- tests/e2e/server-swoole.php | 7 +- 19 files changed, 1015 insertions(+), 1137 deletions(-) diff --git a/README.md b/README.md index 137e384c..c064a03d 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\FPM\Server; Http::get('/hello-world') // Define Route - ->inject('request') - ->inject('response') + ->dependency('request') + ->dependency('response') ->action( function(Request $request, Response $response) { $response @@ -71,7 +71,7 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\FPM\Server; Http::get('/') - ->inject('response') + ->dependency('response') ->action( function(Response $response) { $response->send('Hello from PHP FPM'); @@ -93,8 +93,8 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\Swoole\Server; Http::get('/') - ->inject('request') - ->inject('response') + ->dependency('request') + ->dependency('response') ->action( function(Request $request, Response $response) { $response->send('Hello from Swoole'); @@ -118,7 +118,7 @@ Define an endpoint with params: ```php Http::get('/') ->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true) - ->inject('response') + ->dependency('response') ->action(function(string $name, Response $response) { $response->send('Hello ' . $name); }); @@ -146,20 +146,20 @@ You can provide multiple hooks for each stage. If you do not assign groups to th ```php Http::init() - ->inject('request') + ->dependency('request') ->action(function(Request $request) { \var_dump("Recieved: " . $request->getMethod() . ' ' . $request->getURI()); }); Http::shutdown() - ->inject('response') + ->dependency('response') ->action(function(Response $response) { \var_dump('Responding with status code: ' . $response->getStatusCode()); }); Http::error() - ->inject('error') - ->inject('response') + ->dependency('error') + ->dependency('response') ->action(function(\Throwable $error, Response $response) { $response ->setStatusCode(500) @@ -178,7 +178,7 @@ You can start by defining a group on an endpoint. Keep in mind you can also defi ```php Http::get('/v1/health') ->groups(['api', 'public']) - ->inject('response') + ->dependency('response') ->action( function(Response $response) { $response->send('OK'); @@ -191,8 +191,8 @@ Now you can define hooks that would apply only to specific groups. Remember, hoo ```php Http::init() ->groups(['api']) - ->inject('request') - ->inject('response') + ->dependency('request') + ->dependency('response') ->action(function(Request $request, Response $response) { $apiKey = $request->getHeader('x-api-key', ''); @@ -222,8 +222,8 @@ Inject resource into endpoint action: ```php Http::get('/') - ->inject('timing') - ->inject('response') + ->dependency('timing') + ->dependency('response') ->action(function(float $timing, Response $response) { $response->send('Request Unix timestamp: ' . \strval($timing)); }); @@ -233,7 +233,7 @@ Inject resource into a hook: ```php Http::shutdown() - ->inject('timing') + ->dependency('timing') ->action(function(float $timing) { $difference = \microtime(true) - $timing; \var_dump("Request took: " . $difference . " seconds"); diff --git a/composer.json b/composer.json index b5c168bc..7fcb778a 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ }, "require": { "php": ">=8.0", - "ext-swoole": "*" + "ext-swoole": "*", + "utopia-php/di": "dev-main" }, "require-dev": { "phpunit/phpunit": "^9.5.25", @@ -33,5 +34,11 @@ "swoole/ide-helper": "4.8.3", "phpstan/phpstan": "^1.10", "phpbench/phpbench": "^1.2" - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/utopia-php/di" + } + ] } diff --git a/composer.lock b/composer.lock index cb7278bc..eec563a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,71 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "33b8cf270cfbd8f86cbd1338d81f5140", - "packages": [], + "content-hash": "a0fa34d8715378591c16534833ef0d42", + "packages": [ + { + "name": "utopia-php/di", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/di.git", + "reference": "3f4390e2b64df56cfd2f46c831c30672ac4497c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/di/zipball/3f4390e2b64df56cfd2f46c831c30672ac4497c0", + "reference": "3f4390e2b64df56cfd2f46c831c30672ac4497c0", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25", + "swoole/ide-helper": "4.8.3" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/", + "Tests\\E2E\\": "tests/e2e" + } + }, + "scripts": { + "lint": [ + "vendor/bin/pint --test" + ], + "format": [ + "vendor/bin/pint" + ], + "check": [ + "vendor/bin/phpstan analyse -c phpstan.neon" + ], + "test": [ + "vendor/bin/phpunit --configuration phpunit.xml" + ] + }, + "license": [ + "MIT" + ], + "description": "A simple and lite library for managing dependency injections", + "keywords": [ + "framework", + "http", + "php", + "upf" + ], + "support": { + "source": "https://github.com/utopia-php/di/tree/main", + "issues": "https://github.com/utopia-php/di/issues" + }, + "time": "2024-04-04T13:13:18+00:00" + } + ], "packages-dev": [ { "name": "doctrine/annotations", @@ -232,16 +295,16 @@ }, { "name": "laravel/pint", - "version": "v1.14.0", + "version": "v1.15.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "6b127276e3f263f7bb17d5077e9e0269e61b2a0e" + "reference": "5f288b5e79938cc72f5c298d384e639de87507c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/6b127276e3f263f7bb17d5077e9e0269e61b2a0e", - "reference": "6b127276e3f263f7bb17d5077e9e0269e61b2a0e", + "url": "https://api.github.com/repos/laravel/pint/zipball/5f288b5e79938cc72f5c298d384e639de87507c6", + "reference": "5f288b5e79938cc72f5c298d384e639de87507c6", "shasum": "" }, "require": { @@ -252,13 +315,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.49.0", - "illuminate/view": "^10.43.0", - "larastan/larastan": "^2.8.1", + "friendsofphp/php-cs-fixer": "^3.52.1", + "illuminate/view": "^10.48.4", + "larastan/larastan": "^2.9.2", "laravel-zero/framework": "^10.3.0", - "mockery/mockery": "^1.6.7", + "mockery/mockery": "^1.6.11", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.33.6" + "pestphp/pest": "^2.34.5" }, "bin": [ "builds/pint" @@ -294,7 +357,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-02-20T17:38:05+00:00" + "time": "2024-04-02T14:28:47+00:00" }, { "name": "myclabs/deep-copy", @@ -733,16 +796,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.60", + "version": "1.10.66", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe" + "reference": "94779c987e4ebd620025d9e5fdd23323903950bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd", + "reference": "94779c987e4ebd620025d9e5fdd23323903950bd", "shasum": "" }, "require": { @@ -791,7 +854,7 @@ "type": "tidelift" } ], - "time": "2024-03-07T13:30:19+00:00" + "time": "2024-03-28T16:17:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1114,16 +1177,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.17", + "version": "9.6.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" + "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", + "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", "shasum": "" }, "require": { @@ -1197,7 +1260,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.18" }, "funding": [ { @@ -1213,7 +1276,7 @@ "type": "tidelift" } ], - "time": "2024-02-23T13:14:51+00:00" + "time": "2024-03-21T12:07:32+00:00" }, { "name": "psr/cache", @@ -2169,16 +2232,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -2190,7 +2253,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2211,8 +2274,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -2220,7 +2282,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", @@ -2439,16 +2501,16 @@ }, { "name": "symfony/console", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", + "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", "shasum": "" }, "require": { @@ -2512,7 +2574,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.4" + "source": "https://github.com/symfony/console/tree/v7.0.6" }, "funding": [ { @@ -2528,7 +2590,7 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-01T11:04:53+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2599,16 +2661,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.0.3", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12" + "reference": "408105dff4c104454100730bdfd1a9cdd993f04d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12", - "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d", + "reference": "408105dff4c104454100730bdfd1a9cdd993f04d", "shasum": "" }, "require": { @@ -2642,7 +2704,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.0.3" + "source": "https://github.com/symfony/filesystem/tree/v7.0.6" }, "funding": [ { @@ -2658,7 +2720,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-03-21T19:37:36+00:00" }, { "name": "symfony/finder", @@ -3172,16 +3234,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", "shasum": "" }, "require": { @@ -3234,7 +3296,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" }, "funding": [ { @@ -3250,7 +3312,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-12-19T21:51:00+00:00" }, { "name": "symfony/string", @@ -3390,16 +3452,16 @@ }, { "name": "webmozart/glob", - "version": "4.6.0", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655" + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655", + "url": "https://api.github.com/repos/webmozarts/glob/zipball/8a2842112d6916e61e0e15e316465b611f3abc17", + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17", "shasum": "" }, "require": { @@ -3433,14 +3495,16 @@ "description": "A PHP implementation of Ant's glob.", "support": { "issues": "https://github.com/webmozarts/glob/issues", - "source": "https://github.com/webmozarts/glob/tree/4.6.0" + "source": "https://github.com/webmozarts/glob/tree/4.7.0" }, - "time": "2022-05-24T19:45:58+00:00" + "time": "2024-03-07T20:33:40+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/di": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/Getting-Starting-Guide.md b/docs/Getting-Starting-Guide.md index b0f46a4b..93e7965a 100644 --- a/docs/Getting-Starting-Guide.md +++ b/docs/Getting-Starting-Guide.md @@ -19,8 +19,8 @@ use Swoole\Http\Response as SwooleResponse; $http = new Server("0.0.0.0", 8080); Http::get('/') - ->inject('request') - ->inject('response') + ->dependency('request') + ->dependency('response') ->action( function($request, $response) { // Return raw HTML @@ -63,7 +63,7 @@ Http::put('/todos/:id') ->param('id', "", new Wildcard(), 'id of the todo') ->param('task', "", new Wildcard(), 'name of the todo') ->param('is_complete', true, new Wildcard(), 'task complete or not') - ->inject('response') + ->dependency('response') ->action( function($id, $task, $is_complete, $response) { $path = \realpath('/http/http/todos.json'); @@ -194,7 +194,7 @@ Http::put('/todos/:id') ->param('id', "", new Wildcard(), 'id of the todo') ->param('task', "", new Wildcard(), 'name of the todo') ->param('is_complete', true, new Wildcard(), 'task complete or not') - ->inject('response') + ->dependency('response') ->action( function($id, $task, $is_complete, $response) { $path = \realpath('/http/http/todos.json'); diff --git a/example/src/server.php b/example/src/server.php index 4eb07f71..c7363c33 100644 --- a/example/src/server.php +++ b/example/src/server.php @@ -9,7 +9,7 @@ Http::get('/') ->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true) - ->inject('response') + ->dependency('response') ->action(function (string $name, Response $response) { $response->send('Hello ' . $name); }); diff --git a/src/Http/Adapter/FPM/Server.php b/src/Http/Adapter/FPM/Server.php index e90f0cd7..797459a0 100755 --- a/src/Http/Adapter/FPM/Server.php +++ b/src/Http/Adapter/FPM/Server.php @@ -16,9 +16,6 @@ public function onRequest(callable $callback) $request = new Request(); $response = new Response(); - Http::setResource('fpmRequest', fn () => $request); - Http::setResource('fpmResponse', fn () => $response); - call_user_func($callback, $request, $response, 'fpm'); } diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 9fe73e98..96035ce6 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -26,12 +26,7 @@ public function __construct(string $host, string $port = null, array $settings = public function onRequest(callable $callback) { $this->server->handle('/', function (SwooleRequest $request, SwooleResponse $response) use ($callback) { - $context = \strval(Coroutine::getCid()); - - Http::setResource('swooleRequest', fn () => $request, [], $context); - Http::setResource('swooleResponse', fn () => $response, [], $context); - - call_user_func($callback, new Request($request), new Response($response), $context); + call_user_func($callback, new Request($request), new Response($response)); }); } diff --git a/src/Http/Hook.php b/src/Http/Hook.php index 2266da26..32ab37e7 100644 --- a/src/Http/Hook.php +++ b/src/Http/Hook.php @@ -2,7 +2,9 @@ namespace Utopia\Http; -class Hook +use Utopia\DI\Injection; + +class Hook extends Injection { /** * Description @@ -36,13 +38,6 @@ class Hook */ protected array $labels = []; - /** - * Action Callback - * - * @var callable - */ - protected $action; - /** * Injections * @@ -52,12 +47,6 @@ class Hook */ protected array $injections = []; - public function __construct() - { - $this->action = function (): void { - }; - } - /** * Add Description * @@ -140,7 +129,7 @@ public function getLabel(string $key, mixed $default): mixed */ public function action(callable $action): static { - $this->action = $action; + $this->setCallback($action); return $this; } @@ -152,37 +141,20 @@ public function action(callable $action): static */ public function getAction() { - return $this->action; + return $this->getCallback(); } /** - * Get Injections + * Depenedency * - * @return array - */ - public function getInjections(): array - { - return $this->injections; - } - - /** - * Inject - * - * @param string $injection - * @return static + * @param string $name + * @return self * * @throws Exception */ - public function inject(string $injection): static + public function dependency(string $name): self { - if (array_key_exists($injection, $this->injections)) { - throw new Exception('Injection already declared for '.$injection); - } - - $this->injections[$injection] = [ - 'name' => $injection, - 'order' => count($this->params) + count($this->injections), - ]; + parent::dependency($name); return $this; } @@ -212,6 +184,8 @@ public function param(string $key, mixed $default, Validator|callable $validator 'order' => count($this->params) + count($this->injections), ]; + $this->dependency($key); + return $this; } diff --git a/src/Http/Http.php b/src/Http/Http.php index e136248b..414e4f46 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -2,51 +2,34 @@ namespace Utopia\Http; +use Utopia\DI\Container; +use Utopia\DI\Dependency; + class Http { /** * Request method constants */ public const REQUEST_METHOD_GET = 'GET'; - public const REQUEST_METHOD_POST = 'POST'; - public const REQUEST_METHOD_PUT = 'PUT'; - public const REQUEST_METHOD_PATCH = 'PATCH'; - public const REQUEST_METHOD_DELETE = 'DELETE'; - public const REQUEST_METHOD_OPTIONS = 'OPTIONS'; - public const REQUEST_METHOD_HEAD = 'HEAD'; /** * Mode Type */ public const MODE_TYPE_DEVELOPMENT = 'development'; - public const MODE_TYPE_STAGE = 'stage'; - public const MODE_TYPE_PRODUCTION = 'production'; - /** - * @var array - */ - protected array $resources = [ - 'error' => null, - ]; - /** * @var Files */ protected Files $files; - /** - * @var array - */ - protected static array $resourcesCallbacks = []; - /** * Current running mode * @@ -126,6 +109,11 @@ class Http */ protected Adapter $server; + /** + * @var Container + */ + protected Container $container; + protected string|null $requestClass = null; protected string|null $responseClass = null; @@ -135,18 +123,25 @@ class Http * @param Adapter $server * @param string $timezone */ - public function __construct(Adapter $server, string $timezone) + public function __construct(Adapter $server, Container $container, string $timezone) { \date_default_timezone_set($timezone); $this->files = new Files(); $this->server = $server; + $this->container = $container; } + /** + * Set Request Class + */ public function setResponseClass(string $responseClass) { $this->responseClass = $responseClass; } + /** + * Set Request Class + */ public function setRequestClass(string $requestClass) { $this->requestClass = $requestClass; @@ -299,20 +294,6 @@ public static function error(): Hook return $hook; } - /** - * Get env var - * - * Method for querying env varialbles. If $key is not found $default value will be returned. - * - * @param string $key - * @param string|null $default - * @return string|null - */ - public static function getEnv(string $key, string $default = null): ?string - { - return $_SERVER[$key] ?? $default; - } - /** * Get Mode * @@ -361,81 +342,6 @@ public static function setAllowOverride(bool $value): void Router::setAllowOverride($value); } - /** - * If a resource has been created return it, otherwise create it and then return it - * - * @param string $name - * @param bool $fresh - * @return mixed - * - * @throws Exception - */ - public function getResource(string $name, string $context = 'utopia', bool $fresh = false): mixed - { - if ($name === 'utopia') { - return $this; - } - - $this->resources[$context] ??= []; - - $resourcesCallback = &self::$resourcesCallbacks[$context] ?? []; - if(empty($resourcesCallback) || !\array_key_exists($name, $resourcesCallback)) { - $resourcesCallback = &self::$resourcesCallbacks['utopia']; - } - - if (!\array_key_exists($name, $this->resources[$context]) || $fresh || ($resourcesCallback[$name]['reset'][$context] ?? true)) { - if (!\array_key_exists($name, $resourcesCallback)) { - throw new Exception('Failed to find resource: "' . $name . '"'); - } - - $this->resources[$context][$name] = \call_user_func_array( - $resourcesCallback[$name]['callback'], - $this->getResources($resourcesCallback[$name]['injections'], $context) - ); - } - - $resourcesCallback[$name]['reset'][$context] = false; - return $this->resources[$context][$name]; - } - - /** - * Get Resources By List - * - * @param array $list - * @return array - */ - public function getResources(array $list, string $context = 'utopia'): array - { - $resources = []; - - foreach ($list as $name) { - $resources[$name] = $this->getResource($name, $context); - } - - return $resources; - } - - /** - * Set a new resource callback - * - * @param string $name - * @param callable $callback - * @param array $injections - * @return void - * - * @throws Exception - */ - public static function setResource(string $name, callable $callback, array $injections = [], string $context = 'utopia'): void - { - if ($name === 'utopia') { - throw new Exception("'utopia' is a reserved keyword.", 500); - } - - self::$resourcesCallbacks[$context] ??= []; - - self::$resourcesCallbacks[$context][$name] = ['callback' => $callback, 'injections' => $injections, 'resets' => []]; - } - /** * Is http in production mode? * @@ -478,28 +384,6 @@ public static function getRoutes(): array return Router::getRoutes(); } - /** - * Get the current route - * - * @return null|Route - */ - public function getRoute(): ?Route - { - return $this->route ?? null; - } - - /** - * Set the current route - * - * @param Route $route - */ - public function setRoute(Route $route): self - { - $this->route = $route; - - return $this; - } - /** * Add Route * @@ -585,35 +469,60 @@ public static function onRequest(): Hook public function start() { - $this->server->onRequest(function ($request, $response, $context) { - try { - $this->run($request, $response, $context); - } finally { - if(isset(self::$resourcesCallbacks[$context])) { - unset(self::$resourcesCallbacks[$context]); - } + $this->server->onRequest(function ($request, $response) { + $context = clone $this->container; + $dependency = new Dependency(); + + if(!\is_null($this->requestClass)) { + $request = new $this->requestClass($request); } + + if(!\is_null($this->responseClass)) { + $response = new $this->responseClass($response); + } + + $context = clone $this->container; + + $context->set(clone $dependency + ->setName('request') + ->setCallback(fn () => $request) + ) + ->set(clone $dependency + ->setName('response') + ->setCallback(fn () => $response) + ) + ; + + $this->run($request, $response, $context); }); + $this->server->onStart(function ($server) { - $this->resources['utopia'] ??= []; - $this->resources['utopia']['server'] = $server; - self::setResource('server', function () use ($server) { - return $server; - }); - try { + + $dependency = new Dependency(); + $this->container + ->set($dependency + ->setName('server') + ->setCallback(fn () => $server) + ) + ; + try { foreach (self::$startHooks as $hook) { - $arguments = $this->getArguments($hook, 'utopia', [], []); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($this->container, $hook, [], [])->dependency($hook); } } catch(\Exception $e) { - self::setResource('error', fn () => $e); + + $dependency = new Dependency(); + $this->container->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $arguments = $this->getArguments($error, 'utopia', [], []); - \call_user_func_array($error->getAction(), $arguments); + $this->prepare($this->container, $error, [], [])->dependency($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -636,17 +545,11 @@ public function start() */ public function match(Request $request, bool $fresh = true): ?Route { - if (null !== $this->route && !$fresh) { - return $this->route; - } - $url = \parse_url($request->getURI(), PHP_URL_PATH); $method = $request->getMethod(); $method = (self::REQUEST_METHOD_HEAD == $method) ? self::REQUEST_METHOD_GET : $method; - $this->route = Router::match($method, $url); - - return $this->route; + return Router::match($method, $url); } /** @@ -655,7 +558,7 @@ public function match(Request $request, bool $fresh = true): ?Route * @param Route $route * @param Request $request */ - public function execute(Route $route, Request $request, string $context): static + public function execute(Route $route, Request $request, Container $context): static { $arguments = []; $groups = $route->getGroups(); @@ -665,8 +568,7 @@ public function execute(Route $route, Request $request, string $context): static if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { - $arguments = $this->getArguments($hook, $context, $pathValues, $request->getParams()); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); } } } @@ -674,20 +576,17 @@ public function execute(Route $route, Request $request, string $context): static foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { - $arguments = $this->getArguments($hook, $context, $pathValues, $request->getParams()); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); } } } - $arguments = $this->getArguments($route, $context, $pathValues, $request->getParams()); - \call_user_func_array($route->getAction(), $arguments); + $this->prepare($context, $route, $pathValues, $request->getParams())->dependency($route); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array($group, $hook->getGroups())) { - $arguments = $this->getArguments($hook, $context, $pathValues, $request->getParams()); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); } } } @@ -695,20 +594,23 @@ public function execute(Route $route, Request $request, string $context): static if ($route->getHook()) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array('*', $hook->getGroups())) { - $arguments = $this->getArguments($hook, $context, $pathValues, $request->getParams()); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); } } } } catch (\Throwable $e) { - self::setResource('error', fn () => $e, [], $context); + $dependency = new Dependency(); + $context->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks if (in_array($group, $error->getGroups())) { try { - $arguments = $this->getArguments($error, $context, $pathValues, $request->getParams()); - \call_user_func_array($error->getAction(), $arguments); + $this->prepare($context, $error, $pathValues, $request->getParams())->dependency($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -719,8 +621,7 @@ public function execute(Route $route, Request $request, string $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $arguments = $this->getArguments($error, $context, $pathValues, $request->getParams()); - \call_user_func_array($error->getAction(), $arguments); + $this->prepare($context, $error, $pathValues, $request->getParams())->dependency($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -729,35 +630,51 @@ public function execute(Route $route, Request $request, string $context): static } // Reset resources for the context - $this->resources[$context] = []; + unset($context); return $this; } /** - * Get Arguments + * Prepare hook for injection, add dependencies, run validation. * * @param Hook $hook * @param array $values * @param array $requestParams - * @return array + * @return Container * * @throws Exception */ - protected function getArguments(Hook $hook, string $context, array $values, array $requestParams): array + protected function prepare(Container $context, Hook $hook, array $values = [], array $requestParams = []): Container { - $arguments = []; foreach ($hook->getParams() as $key => $param) { // Get value from route or request object $existsInRequest = \array_key_exists($key, $requestParams); $existsInValues = \array_key_exists($key, $values); $paramExists = $existsInRequest || $existsInValues; - $arg = $existsInRequest ? $requestParams[$key] : $param['default']; + if (\is_callable($arg)) { - $arg = \call_user_func_array($arg, $this->getResources($param['injections'])); + + $dependency = new Dependency(); + $dependency + ->setName($key) + ->setCallback($arg) + ; + + foreach ($param['injections'] as $injection) { + $dependency->dependency($injection); + } + + $context->set($dependency); } + $value = $existsInValues ? $values[$key] : $arg; + // TODO @eldad should we add dependency injection for values as well? + + /** + * Validation + */ if (!$param['skipValidation']) { if (!$paramExists && !$param['optional']) { throw new Exception('Param "' . $key . '" is not optional.', 400); @@ -769,14 +686,9 @@ protected function getArguments(Hook $hook, string $context, array $values, arra } $hook->setParamValue($key, $value); - $arguments[$param['order']] = $value; - } - foreach ($hook->getInjections() as $key => $injection) { - $arguments[$injection['order']] = $this->getResource($injection['name'], $context); + return $context; } - - return $arguments; } /** @@ -788,40 +700,27 @@ protected function getArguments(Hook $hook, string $context, array $values, arra * @param Request $request * @param Response $response; */ - public function run(Request $request, Response $response, string $context): static + public function run(Container $context): static { - if(!\is_null($this->requestClass)) { - $request = new $this->requestClass($request); - } - - if(!\is_null($this->responseClass)) { - $response = new $this->responseClass($response); - } - - $this->resources[$context] = []; - $this->resources[$context]['request'] = $request; - $this->resources[$context]['response'] = $response; - - self::setResource('context', fn () => $context, [], $context); - - self::setResource('request', fn () => $request, [], $context); - - self::setResource('response', fn () => $response, [], $context); - + $request = $context->get('request'); + try { foreach (self::$requestHooks as $hook) { - $arguments = $this->getArguments($hook, $context, [], []); - \call_user_func_array($hook->getAction(), $arguments); + $this->prepare($context, $hook)->dependency($hook); } } catch(\Exception $e) { - self::setResource('error', fn () => $e, [], $context); + $dependency = new Dependency(); + $context->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $arguments = $this->getArguments($error, $context, [], []); - \call_user_func_array($error->getAction(), $arguments); + $this->prepare($context, $error)->dependency($hook); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -840,11 +739,17 @@ public function run(Request $request, Response $response, string $context): stat return $this; } + $method = $request->getMethod(); $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; - self::setResource('route', fn () => $route, [], $context); + $dependency = new Dependency(); + $context->set($dependency + ->setName('route') + ->setCallback(fn () => $route) + ) + ; if (self::REQUEST_METHOD_HEAD == $method) { $method = self::REQUEST_METHOD_GET; @@ -857,7 +762,7 @@ public function run(Request $request, Response $response, string $context): stat foreach (self::$options as $option) { // Group options hooks /** @var Hook $option */ if (in_array($group, $option->getGroups())) { - \call_user_func_array($option->getAction(), $this->getArguments($option, $context, [], $request->getParams())); + $this->prepare($context, $option, [], $request->getParams())->dependency($option); } } } @@ -865,17 +770,21 @@ public function run(Request $request, Response $response, string $context): stat foreach (self::$options as $option) { // Global options hooks /** @var Hook $option */ if (in_array('*', $option->getGroups())) { - \call_user_func_array($option->getAction(), $this->getArguments($option, $context, [], $request->getParams())); + $this->prepare($context, $option, [], $request->getParams())->dependency($option); } } } catch (\Throwable $e) { foreach (self::$errors as $error) { // Global error hooks /** @var Hook $error */ if (in_array('*', $error->getGroups())) { - self::setResource('error', function () use ($e) { - return $e; - }, [], $context); - \call_user_func_array($error->getAction(), $this->getArguments($error, $context, [], $request->getParams())); + $dependency = new Dependency(); + $this->container->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; + + $this->prepare($context, $error, [], $request->getParams())->dependency($error); } } } @@ -885,11 +794,15 @@ public function run(Request $request, Response $response, string $context): stat if (null === $route && null !== self::$wildcardRoute) { $route = self::$wildcardRoute; - $this->route = $route; $path = \parse_url($request->getURI(), PHP_URL_PATH); $route->path($path); - self::setResource('route', fn () => $route, [], $context); + $dependency = new Dependency(); + $context->set($dependency + ->setName('route') + ->setCallback(fn () => $route) + ) + ; } if (null !== $route) { @@ -899,33 +812,41 @@ public function run(Request $request, Response $response, string $context): stat foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks if (in_array($group, $option->getGroups())) { - \call_user_func_array($option->getAction(), $this->getArguments($option, $context, [], $request->getParams())); + $this->prepare($context, $option, [], $request->getParams())->dependency($option); } } } foreach (self::$options as $option) { // Global options hooks if (in_array('*', $option->getGroups())) { - \call_user_func_array($option->getAction(), $this->getArguments($option, $context, [], $request->getParams())); + $this->prepare($context, $option, [], $request->getParams())->dependency($option); } } } catch (\Throwable $e) { foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { - self::setResource('error', function () use ($e) { - return $e; - }, [], $context); - \call_user_func_array($error->getAction(), $this->getArguments($error, $context, [], $request->getParams())); + $dependency = new Dependency(); + $this->container->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; + + $this->prepare($context, $error, [], $request->getParams())->dependency($error); } } } } else { foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { - self::setResource('error', function () { - return new Exception('Not Found', 404); - }, [], $context); - \call_user_func_array($error->getAction(), $this->getArguments($error, $context, [], $request->getParams())); + $dependency = new Dependency(); + $this->container->set($dependency + ->setName('error') + ->setCallback(fn () => $e) + ) + ; + + $this->prepare($context, $error, [], $request->getParams())->dependency($error); } } } @@ -945,7 +866,7 @@ public function run(Request $request, Response $response, string $context): stat * * @throws Exception */ - protected function validate(string $key, array $param, mixed $value, $context): void + protected function validate(string $key, array $param, mixed $value, Container $context): void { if ($param['optional'] && \is_null($value)) { return; @@ -954,7 +875,18 @@ protected function validate(string $key, array $param, mixed $value, $context): $validator = $param['validator']; // checking whether the class exists if (\is_callable($validator)) { - $validator = \call_user_func_array($validator, $this->getResources($param['injections'], $context)); + + $dependency = new Dependency(); + $dependency + ->setName($key) + ->setCallback($param['validator']) + ; + + foreach ($param['injections'] as $injection) { + $dependency->dependency($injection); + } + + $validator = $context->dependency($dependency); } if (!$validator instanceof Validator) { // is the validator object an instance of the Validator class @@ -974,7 +906,6 @@ protected function validate(string $key, array $param, mixed $value, $context): public static function reset(): void { Router::reset(); - self::$resourcesCallbacks = []; self::$mode = ''; self::$errors = []; self::$init = []; diff --git a/src/Http/Route.php b/src/Http/Route.php index 8a7d0620..f2dd40ae 100755 --- a/src/Http/Route.php +++ b/src/Http/Route.php @@ -51,8 +51,6 @@ public function __construct(string $method, string $path) $this->path($path); $this->method = $method; $this->order = ++self::$counter; - $this->action = function (): void { - }; } /** diff --git a/tests/HookTest.php b/tests/HookTest.php index 458cf9ad..2e2fe55c 100644 --- a/tests/HookTest.php +++ b/tests/HookTest.php @@ -1,101 +1,101 @@ hook = new Hook(); - } +// public function setUp(): void +// { +// $this->hook = new Hook(); +// } - public function testDescriptionCanBeSet() - { - $this->assertEquals('', $this->hook->getDesc()); +// public function testDescriptionCanBeSet() +// { +// $this->assertEquals('', $this->hook->getDesc()); - $this->hook->desc('new hook'); +// $this->hook->desc('new hook'); - $this->assertEquals('new hook', $this->hook->getDesc()); - } +// $this->assertEquals('new hook', $this->hook->getDesc()); +// } - public function testGroupsCanBeSet() - { - $this->assertEquals([], $this->hook->getGroups()); +// public function testGroupsCanBeSet() +// { +// $this->assertEquals([], $this->hook->getGroups()); - $this->hook->groups(['api', 'homepage']); +// $this->hook->groups(['api', 'homepage']); - $this->assertEquals(['api', 'homepage'], $this->hook->getGroups()); - } +// $this->assertEquals(['api', 'homepage'], $this->hook->getGroups()); +// } - public function testActionCanBeSet() - { - $this->assertEquals(function () { - }, $this->hook->getAction()); +// public function testActionCanBeSet() +// { +// $this->assertEquals(function () { +// }, $this->hook->getAction()); - $this->hook->action(fn () => 'hello world'); +// $this->hook->action(fn () => 'hello world'); - $this->assertEquals('hello world', $this->hook->getAction()()); - } +// $this->assertEquals('hello world', $this->hook->getAction()()); +// } - public function testParamCanBeSet() - { - $this->assertEquals([], $this->hook->getParams()); +// public function testParamCanBeSet() +// { +// $this->assertEquals([], $this->hook->getParams()); - $this->hook - ->param('x', '', new Text(10)) - ->param('y', '', new Text(10)); +// $this->hook +// ->param('x', '', new Text(10)) +// ->param('y', '', new Text(10)); - $this->assertCount(2, $this->hook->getParams()); - } +// $this->assertCount(2, $this->hook->getParams()); +// } - public function testResourcesCanBeInjected() - { - $this->assertEquals([], $this->hook->getInjections()); +// public function testResourcesCanBeInjected() +// { +// $this->assertEquals([], $this->hook->getInjections()); - $this->hook - ->inject('user') - ->inject('time') - ->action(function () { - }); +// $this->hook +// ->dependency('user') +// ->dependency('time') +// ->action(function () { +// }); - $this->assertCount(2, $this->hook->getInjections()); - $this->assertEquals('user', $this->hook->getInjections()['user']['name']); - $this->assertEquals('time', $this->hook->getInjections()['time']['name']); - } +// $this->assertCount(2, $this->hook->getInjections()); +// $this->assertEquals('user', $this->hook->getInjections()['user']['name']); +// $this->assertEquals('time', $this->hook->getInjections()['time']['name']); +// } - public function testParamValuesCanBeSet() - { - $this->assertEquals([], $this->hook->getParams()); +// public function testParamValuesCanBeSet() +// { +// $this->assertEquals([], $this->hook->getParams()); - $values = [ - 'x' => 'hello', - 'y' => 'world', - ]; +// $values = [ +// 'x' => 'hello', +// 'y' => 'world', +// ]; - $this->hook - ->param('x', '', new Numeric()) - ->param('y', '', new Numeric()); +// $this->hook +// ->param('x', '', new Numeric()) +// ->param('y', '', new Numeric()); - foreach ($this->hook->getParams() as $key => $param) { - $this->hook->setParamValue($key, $values[$key]); - } +// foreach ($this->hook->getParams() as $key => $param) { +// $this->hook->setParamValue($key, $values[$key]); +// } - $this->assertCount(2, $this->hook->getParams()); - $this->assertEquals('hello', $this->hook->getParams()['x']['value']); - $this->assertEquals('world', $this->hook->getParams()['y']['value']); - } +// $this->assertCount(2, $this->hook->getParams()); +// $this->assertEquals('hello', $this->hook->getParams()['x']['value']); +// $this->assertEquals('world', $this->hook->getParams()['y']['value']); +// } - public function tearDown(): void - { - $this->hook = null; - } -} +// public function tearDown(): void +// { +// $this->hook = null; +// } +// } diff --git a/tests/HttpTest.php b/tests/HttpTest.php index 0d314cd3..31b51148 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -1,619 +1,545 @@ http = new Http(new Server(), 'Asia/Tel_Aviv'); - $this->saveRequest(); - } - - public function tearDown(): void - { - $this->http = null; - $this->restoreRequest(); - } - - protected function saveRequest(): void - { - $this->method = $_SERVER['REQUEST_METHOD'] ?? null; - $this->uri = $_SERVER['REQUEST_URI'] ?? null; - } - - protected function restoreRequest(): void - { - $_SERVER['REQUEST_METHOD'] = $this->method; - $_SERVER['REQUEST_URI'] = $this->uri; - } - - public function testCanGetDifferentModes(): void - { - $this->assertEmpty(Http::getMode()); - $this->assertFalse(Http::isProduction()); - $this->assertFalse(Http::isDevelopment()); - $this->assertFalse(Http::isStage()); - - Http::setMode(Http::MODE_TYPE_PRODUCTION); - - $this->assertEquals(Http::MODE_TYPE_PRODUCTION, Http::getMode()); - $this->assertTrue(Http::isProduction()); - $this->assertFalse(Http::isDevelopment()); - $this->assertFalse(Http::isStage()); - - Http::setMode(Http::MODE_TYPE_DEVELOPMENT); - - $this->assertEquals(Http::MODE_TYPE_DEVELOPMENT, Http::getMode()); - $this->assertFalse(Http::isProduction()); - $this->assertTrue(Http::isDevelopment()); - $this->assertFalse(Http::isStage()); - - Http::setMode(Http::MODE_TYPE_STAGE); - - $this->assertEquals(Http::MODE_TYPE_STAGE, Http::getMode()); - $this->assertFalse(Http::isProduction()); - $this->assertFalse(Http::isDevelopment()); - $this->assertTrue(Http::isStage()); - } - - public function testCanGetEnvironmentVariable(): void - { - // Mock - $_SERVER['key'] = 'value'; - - $this->assertEquals(Http::getEnv('key'), 'value'); - $this->assertEquals(Http::getEnv('unknown', 'test'), 'test'); - } - - public function testCanGetResources(): void - { - Http::setResource('rand', fn () => rand()); - Http::setResource('first', fn ($second) => "first-{$second}", ['second']); - Http::setResource('second', fn () => 'second'); - - $second = $this->http->getResource('second', '1'); - $first = $this->http->getResource('first', '1'); - $this->assertEquals('second', $second); - $this->assertEquals('first-second', $first); - - $resource = $this->http->getResource('rand', '1'); - - $this->assertNotEmpty($resource); - $this->assertEquals($resource, $this->http->getResource('rand', '1')); - $this->assertEquals($resource, $this->http->getResource('rand', '1')); - $this->assertEquals($resource, $this->http->getResource('rand', '1')); - - // Default Params - $route = new Route('GET', '/path'); - - $route - ->inject('rand') - ->param('x', 'x-def', new Text(200), 'x param', true) - ->param('y', 'y-def', new Text(200), 'y param', true) - ->action(function ($x, $y, $rand) { - echo $x . '-' . $y . '-' . $rand; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('x-def-y-def-' . $resource, $result); - } - - public function testCanGetDefaultValueWithFunction(): void - { - Http::setResource('first', fn ($second) => "first-{$second}", ['second']); - Http::setResource('second', fn () => 'second'); - - $second = $this->http->getResource('second'); - $first = $this->http->getResource('first'); - $this->assertEquals('second', $second); - $this->assertEquals('first-second', $first); - - // Default Value using function - $route = new Route('GET', '/path'); - - $route - ->param('x', function ($first, $second) { - return $first . '-' . $second; - }, new Text(200), 'x param', true, ['first', 'second']) - ->action(function ($x) { - echo $x; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('first-second-second', $result); - } - - public function testCanExecuteRoute(): void - { - Http::setResource('rand', fn () => rand()); - $resource = $this->http->getResource('rand', '1'); - - $this->http - ->error() - ->inject('error') - ->action(function ($error) { - echo 'error: ' . $error->getMessage(); - }); - - // Default Params - $route = new Route('GET', '/path'); - - $route - ->param('x', 'x-def', new Text(200), 'x param', true) - ->param('y', 'y-def', new Text(200), 'y param', true) - ->action(function ($x, $y) { - echo $x . '-' . $y; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - // With Params - $resource = $this->http->getResource('rand', '1'); - $route = new Route('GET', '/path'); - - $route - ->param('x', 'x-def', new Text(200), 'x param', true) - ->param('y', 'y-def', new Text(200), 'y param', true) - ->inject('rand') - ->param('z', 'z-def', function ($rand) { - echo $rand . '-'; - - return new Text(200); - }, 'z param', true, ['rand']) - ->action(function ($x, $y, $z, $rand) { - echo $x . '-', $y; - }); - - \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); - $this->http->execute($route, $request, '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals($resource . '-param-x-param-y', $result); - - // With Error - $resource = $this->http->getResource('rand', '1'); - $route = new Route('GET', '/path'); - - $route - ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) - ->param('y', 'y-def', new Text(1, min: 0), 'y param', false) - ->action(function ($x, $y) { - echo $x . '-', $y; - }); - - \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($route, $request, '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); - - // With Hooks - $resource = $this->http->getResource('rand', '1'); - $this->http - ->init() - ->inject('rand') - ->action(function ($rand) { - echo 'init-' . $rand . '-'; - }); - - $this->http - ->shutdown() - ->action(function () { - echo '-shutdown'; - }); - - $this->http - ->init() - ->groups(['api']) - ->action(function () { - echo '(init-api)-'; - }); - - $this->http - ->shutdown() - ->groups(['api']) - ->action(function () { - echo '-(shutdown-api)'; - }); - - $this->http - ->init() - ->groups(['homepage']) - ->action(function () { - echo '(init-homepage)-'; - }); - - $this->http - ->shutdown() - ->groups(['homepage']) - ->action(function () { - echo '-(shutdown-homepage)'; - }); - - $route = new Route('GET', '/path'); - - $route - ->groups(['api']) - ->param('x', 'x-def', new Text(200), 'x param', false) - ->param('y', 'y-def', new Text(200), 'y param', false) - ->action(function ($x, $y) { - echo $x . '-', $y; - }); - - $homepage = new Route('GET', '/path'); - - $homepage - ->groups(['homepage']) - ->param('x', 'x-def', new Text(200), 'x param', false) - ->param('y', 'y-def', new Text(200), 'y param', false) - ->action(function ($x, $y) { - echo $x . '*', $y; - }); - - \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($route, $request, '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); - - $resource = $this->http->getResource('rand', '1'); - \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($homepage, $request, '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('init-' . $resource . '-(init-homepage)-param-x*param-y-(shutdown-homepage)-shutdown', $result); - } - - public function testCanAddAndExecuteHooks() - { - $this->http - ->init() - ->action(function () { - echo '(init)-'; - }); - - $this->http - ->shutdown() - ->action(function () { - echo '-(shutdown)'; - }); - - // Default Params - $route = new Route('GET', '/path'); - $route - ->param('x', 'x-def', new Text(200), 'x param', true) - ->action(function ($x) { - echo $x; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('(init)-x-def-(shutdown)', $result); - - // Default Params - $route = new Route('GET', '/path'); - $route - ->param('x', 'x-def', new Text(200), 'x param', true) - ->hook(false) - ->action(function ($x) { - echo $x; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('x-def', $result); - } - - public function testAllowRouteOverrides() - { - Http::setAllowOverride(false); - $this->assertFalse(Http::getAllowOverride()); - Http::get('/')->action(function () { - echo 'Hello first'; - }); - - try { - Http::get('/')->action(function () { - echo 'Hello second'; - }); - $this->fail('Failed to throw exception'); - } catch (\Exception $e) { - // Threw exception as expected - $this->assertEquals('Route for (GET:) already registered.', $e->getMessage()); - } - - // Test success - Http::setAllowOverride(true); - $this->assertTrue(Http::getAllowOverride()); - Http::get('/')->action(function () { - echo 'Hello first'; - }); - - Http::get('/')->action(function () { - echo 'Hello second'; - }); - } - - public function testCanHookThrowExceptions() - { - $this->http - ->init() - ->param('y', '', new Text(5), 'y param', false) - ->action(function ($y) { - echo '(init)-' . $y . '-'; - }); - - $this->http - ->error() - ->inject('error') - ->action(function ($error) { - echo 'error-' . $error->getMessage(); - }); - - $this->http - ->shutdown() - ->action(function () { - echo '-(shutdown)'; - }); - - // param not provided for init - $route = new Route('GET', '/path'); - $route - ->param('x', 'x-def', new Text(200), 'x param', true) - ->action(function ($x) { - echo $x; - }); - - \ob_start(); - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('error-Param "y" is not optional.', $result); - - \ob_start(); - $_GET['y'] = 'y-def'; - $this->http->execute($route, new Request(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('(init)-y-def-x-def-(shutdown)', $result); - } - - public function testCanSetRoute() - { - $route = new Route('GET', '/path'); - - $this->assertEquals($this->http->getRoute(), null); - $this->http->setRoute($route); - $this->assertEquals($this->http->getRoute(), $route); - } - - public function providerRouteMatching(): array - { - return [ - 'GET request' => [Http::REQUEST_METHOD_GET, '/path1'], - 'GET request on different route' => [Http::REQUEST_METHOD_GET, '/path2'], - 'GET request with trailing slash #1' => [Http::REQUEST_METHOD_GET, '/path3', '/path3/'], - 'GET request with trailing slash #2' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3/'], - 'GET request with trailing slash #3' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3'], - 'POST request' => [Http::REQUEST_METHOD_POST, '/path1'], - 'PUT request' => [Http::REQUEST_METHOD_PUT, '/path1'], - 'PATCH request' => [Http::REQUEST_METHOD_PATCH, '/path1'], - 'DELETE request' => [Http::REQUEST_METHOD_DELETE, '/path1'], - '1 separators' => [Http::REQUEST_METHOD_GET, '/a/'], - '2 separators' => [Http::REQUEST_METHOD_GET, '/a/b'], - '3 separators' => [Http::REQUEST_METHOD_GET, '/a/b/c'] - ]; - } - - /** - * @dataProvider providerRouteMatching - */ - public function testCanMatchRoute(string $method, string $path, string $url = null): void - { - $url ??= $path; - $expected = null; - - switch ($method) { - case Http::REQUEST_METHOD_GET: - $expected = Http::get($path); - break; - case Http::REQUEST_METHOD_POST: - $expected = Http::post($path); - break; - case Http::REQUEST_METHOD_PUT: - $expected = Http::put($path); - break; - case Http::REQUEST_METHOD_PATCH: - $expected = Http::patch($path); - break; - case Http::REQUEST_METHOD_DELETE: - $expected = Http::delete($path); - break; - } - - $_SERVER['REQUEST_METHOD'] = $method; - $_SERVER['REQUEST_URI'] = $url; - - $this->assertEquals($expected, $this->http->match(new Request())); - $this->assertEquals($expected, $this->http->getRoute()); - } - - public function testNoMismatchRoute(): void - { - $requests = [ - [ - 'path' => '/d/:id', - 'url' => '/d/' - ], - [ - 'path' => '/d/:id/e/:id2', - 'url' => '/d/123/e/' - ], - [ - 'path' => '/d/:id/e/:id2/f/:id3', - 'url' => '/d/123/e/456/f/' - ], - ]; - - foreach ($requests as $request) { - Http::get($request['path']); - - $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; - $_SERVER['REQUEST_URI'] = $request['url']; - - $route = $this->http->match(new Request(), fresh: true); - - $this->assertEquals(null, $route); - $this->assertEquals(null, $this->http->getRoute()); - } - } - - public function testCanMatchFreshRoute(): void - { - $route1 = Http::get('/path1'); - $route2 = Http::get('/path2'); - - try { - // Match first request - $_SERVER['REQUEST_METHOD'] = 'HEAD'; - $_SERVER['REQUEST_URI'] = '/path1'; - $matched = $this->http->match(new Request()); - $this->assertEquals($route1, $matched); - $this->assertEquals($route1, $this->http->getRoute()); - - // Second request match returns cached route - $_SERVER['REQUEST_METHOD'] = 'HEAD'; - $_SERVER['REQUEST_URI'] = '/path2'; - $request2 = new Request(); - $matched = $this->http->match($request2, fresh: false); - $this->assertEquals($route1, $matched); - $this->assertEquals($route1, $this->http->getRoute()); - - // Fresh match returns new route - $matched = $this->http->match($request2, fresh: true); - $this->assertEquals($route2, $matched); - $this->assertEquals($route2, $this->http->getRoute()); - } catch (\Exception $e) { - $this->fail($e->getMessage()); - } - } - - public function testCanRunRequest(): void - { - // Test head requests - - $method = (isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null; - $uri = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : null; - - $_SERVER['REQUEST_METHOD'] = 'HEAD'; - $_SERVER['REQUEST_URI'] = '/path'; - - Http::get('/path') - ->inject('response') - ->action(function ($response) { - $response->send('HELLO'); - }); - - \ob_start(); - $this->http->run(new Request(), new Response(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $_SERVER['REQUEST_METHOD'] = $method; - $_SERVER['REQUEST_URI'] = $uri; - - $this->assertStringNotContainsString('HELLO', $result); - } - - public function testWildcardRoute(): void - { - $method = $_SERVER['REQUEST_METHOD'] ?? null; - $uri = $_SERVER['REQUEST_URI'] ?? null; - - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_SERVER['REQUEST_URI'] = '/unknown_path'; - - Http::init() - ->action(function () { - $route = $this->http->getRoute(); - Http::setResource('myRoute', fn () => $route); - }); - - - Http::wildcard() - ->inject('myRoute') - ->inject('response') - ->action(function (mixed $myRoute, $response) { - if ($myRoute == null) { - $response->send('ROUTE IS NULL!'); - } else { - $response->send('HELLO'); - } - }); - - \ob_start(); - @$this->http->run(new Request(), new Response(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('HELLO', $result); - - \ob_start(); - $req = new Request(); - $req = $req->setMethod('OPTIONS'); - @$this->http->run($req, new Response(), '1'); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('', $result); - - $_SERVER['REQUEST_METHOD'] = $method; - $_SERVER['REQUEST_URI'] = $uri; - } -} +// namespace Utopia\Http; + +// use PHPUnit\Framework\TestCase; +// use Utopia\DI\Container; +// use Utopia\Http\Tests\UtopiaFPMRequestTest; +// use Utopia\Http\Validator\Text; +// use Utopia\Http\Adapter\FPM\Request; +// use Utopia\Http\Adapter\FPM\Response; +// use Utopia\Http\Adapter\FPM\Server; + +// class HttpTest extends TestCase +// { +// protected ?Http $http; + +// protected ?string $method; + +// protected ?string $uri; + +// public function setUp(): void +// { +// Http::reset(); +// $this->http = new Http(new Server(), new Container(), 'Asia/Tel_Aviv'); +// $this->saveRequest(); +// } + +// public function tearDown(): void +// { +// $this->http = null; +// $this->restoreRequest(); +// } + +// protected function saveRequest(): void +// { +// $this->method = $_SERVER['REQUEST_METHOD'] ?? null; +// $this->uri = $_SERVER['REQUEST_URI'] ?? null; +// } + +// protected function restoreRequest(): void +// { +// $_SERVER['REQUEST_METHOD'] = $this->method; +// $_SERVER['REQUEST_URI'] = $this->uri; +// } + +// public function testCanGetDifferentModes(): void +// { +// $this->assertEmpty(Http::getMode()); +// $this->assertFalse(Http::isProduction()); +// $this->assertFalse(Http::isDevelopment()); +// $this->assertFalse(Http::isStage()); + +// Http::setMode(Http::MODE_TYPE_PRODUCTION); + +// $this->assertEquals(Http::MODE_TYPE_PRODUCTION, Http::getMode()); +// $this->assertTrue(Http::isProduction()); +// $this->assertFalse(Http::isDevelopment()); +// $this->assertFalse(Http::isStage()); + +// Http::setMode(Http::MODE_TYPE_DEVELOPMENT); + +// $this->assertEquals(Http::MODE_TYPE_DEVELOPMENT, Http::getMode()); +// $this->assertFalse(Http::isProduction()); +// $this->assertTrue(Http::isDevelopment()); +// $this->assertFalse(Http::isStage()); + +// Http::setMode(Http::MODE_TYPE_STAGE); + +// $this->assertEquals(Http::MODE_TYPE_STAGE, Http::getMode()); +// $this->assertFalse(Http::isProduction()); +// $this->assertFalse(Http::isDevelopment()); +// $this->assertTrue(Http::isStage()); +// } + +// public function testCanExecuteRoute(): void +// { +// Http::setResource('rand', fn () => rand()); +// $resource = $this->http->getResource('rand', '1'); + +// $this->http +// ->error() +// ->dependency('error') +// ->action(function ($error) { +// echo 'error: ' . $error->getMessage(); +// }); + +// // Default Params +// $route = new Route('GET', '/path'); + +// $route +// ->param('x', 'x-def', new Text(200), 'x param', true) +// ->param('y', 'y-def', new Text(200), 'y param', true) +// ->action(function ($x, $y) { +// echo $x . '-' . $y; +// }); + +// \ob_start(); +// $this->http->execute($route, new Request(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// // With Params +// $resource = $this->http->getResource('rand', '1'); +// $route = new Route('GET', '/path'); + +// $route +// ->param('x', 'x-def', new Text(200), 'x param', true) +// ->param('y', 'y-def', new Text(200), 'y param', true) +// ->dependency('rand') +// ->param('z', 'z-def', function ($rand) { +// echo $rand . '-'; + +// return new Text(200); +// }, 'z param', true, ['rand']) +// ->action(function ($x, $y, $z, $rand) { +// echo $x . '-', $y; +// }); + +// \ob_start(); +// $request = new UtopiaFPMRequestTest(); +// $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); +// $this->http->execute($route, $request, '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals($resource . '-param-x-param-y', $result); + +// // With Error +// $resource = $this->http->getResource('rand', '1'); +// $route = new Route('GET', '/path'); + +// $route +// ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) +// ->param('y', 'y-def', new Text(1, min: 0), 'y param', false) +// ->action(function ($x, $y) { +// echo $x . '-', $y; +// }); + +// \ob_start(); +// $request = new UtopiaFPMRequestTest(); +// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); +// $this->http->execute($route, $request, '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); + +// // With Hooks +// $resource = $this->http->getResource('rand', '1'); +// $this->http +// ->init() +// ->dependency('rand') +// ->action(function ($rand) { +// echo 'init-' . $rand . '-'; +// }); + +// $this->http +// ->shutdown() +// ->action(function () { +// echo '-shutdown'; +// }); + +// $this->http +// ->init() +// ->groups(['api']) +// ->action(function () { +// echo '(init-api)-'; +// }); + +// $this->http +// ->shutdown() +// ->groups(['api']) +// ->action(function () { +// echo '-(shutdown-api)'; +// }); + +// $this->http +// ->init() +// ->groups(['homepage']) +// ->action(function () { +// echo '(init-homepage)-'; +// }); + +// $this->http +// ->shutdown() +// ->groups(['homepage']) +// ->action(function () { +// echo '-(shutdown-homepage)'; +// }); + +// $route = new Route('GET', '/path'); + +// $route +// ->groups(['api']) +// ->param('x', 'x-def', new Text(200), 'x param', false) +// ->param('y', 'y-def', new Text(200), 'y param', false) +// ->action(function ($x, $y) { +// echo $x . '-', $y; +// }); + +// $homepage = new Route('GET', '/path'); + +// $homepage +// ->groups(['homepage']) +// ->param('x', 'x-def', new Text(200), 'x param', false) +// ->param('y', 'y-def', new Text(200), 'y param', false) +// ->action(function ($x, $y) { +// echo $x . '*', $y; +// }); + +// \ob_start(); +// $request = new UtopiaFPMRequestTest(); +// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); +// $this->http->execute($route, $request, '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); + +// $resource = $this->http->getResource('rand', '1'); +// \ob_start(); +// $request = new UtopiaFPMRequestTest(); +// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); +// $this->http->execute($homepage, $request, '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('init-' . $resource . '-(init-homepage)-param-x*param-y-(shutdown-homepage)-shutdown', $result); +// } + +// public function testCanAddAndExecuteHooks() +// { +// $this->http +// ->init() +// ->action(function () { +// echo '(init)-'; +// }); + +// $this->http +// ->shutdown() +// ->action(function () { +// echo '-(shutdown)'; +// }); + +// // Default Params +// $route = new Route('GET', '/path'); +// $route +// ->param('x', 'x-def', new Text(200), 'x param', true) +// ->action(function ($x) { +// echo $x; +// }); + +// \ob_start(); +// $this->http->execute($route, new Request(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('(init)-x-def-(shutdown)', $result); + +// // Default Params +// $route = new Route('GET', '/path'); +// $route +// ->param('x', 'x-def', new Text(200), 'x param', true) +// ->hook(false) +// ->action(function ($x) { +// echo $x; +// }); + +// \ob_start(); +// $this->http->execute($route, new Request(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('x-def', $result); +// } + +// public function testAllowRouteOverrides() +// { +// Http::setAllowOverride(false); +// $this->assertFalse(Http::getAllowOverride()); +// Http::get('/')->action(function () { +// echo 'Hello first'; +// }); + +// try { +// Http::get('/')->action(function () { +// echo 'Hello second'; +// }); +// $this->fail('Failed to throw exception'); +// } catch (\Exception $e) { +// // Threw exception as expected +// $this->assertEquals('Route for (GET:) already registered.', $e->getMessage()); +// } + +// // Test success +// Http::setAllowOverride(true); +// $this->assertTrue(Http::getAllowOverride()); +// Http::get('/')->action(function () { +// echo 'Hello first'; +// }); + +// Http::get('/')->action(function () { +// echo 'Hello second'; +// }); +// } + +// public function testCanHookThrowExceptions() +// { +// $this->http +// ->init() +// ->param('y', '', new Text(5), 'y param', false) +// ->action(function ($y) { +// echo '(init)-' . $y . '-'; +// }); + +// $this->http +// ->error() +// ->dependency('error') +// ->action(function ($error) { +// echo 'error-' . $error->getMessage(); +// }); + +// $this->http +// ->shutdown() +// ->action(function () { +// echo '-(shutdown)'; +// }); + +// // param not provided for init +// $route = new Route('GET', '/path'); +// $route +// ->param('x', 'x-def', new Text(200), 'x param', true) +// ->action(function ($x) { +// echo $x; +// }); + +// \ob_start(); +// $this->http->execute($route, new Request(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('error-Param "y" is not optional.', $result); + +// \ob_start(); +// $_GET['y'] = 'y-def'; +// $this->http->execute($route, new Request(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('(init)-y-def-x-def-(shutdown)', $result); +// } + +// public function testCanSetRoute() +// { +// $route = new Route('GET', '/path'); + +// $this->assertEquals($this->http->getRoute(), null); +// $this->http->setRoute($route); +// $this->assertEquals($this->http->getRoute(), $route); +// } + +// public function providerRouteMatching(): array +// { +// return [ +// 'GET request' => [Http::REQUEST_METHOD_GET, '/path1'], +// 'GET request on different route' => [Http::REQUEST_METHOD_GET, '/path2'], +// 'GET request with trailing slash #1' => [Http::REQUEST_METHOD_GET, '/path3', '/path3/'], +// 'GET request with trailing slash #2' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3/'], +// 'GET request with trailing slash #3' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3'], +// 'POST request' => [Http::REQUEST_METHOD_POST, '/path1'], +// 'PUT request' => [Http::REQUEST_METHOD_PUT, '/path1'], +// 'PATCH request' => [Http::REQUEST_METHOD_PATCH, '/path1'], +// 'DELETE request' => [Http::REQUEST_METHOD_DELETE, '/path1'], +// '1 separators' => [Http::REQUEST_METHOD_GET, '/a/'], +// '2 separators' => [Http::REQUEST_METHOD_GET, '/a/b'], +// '3 separators' => [Http::REQUEST_METHOD_GET, '/a/b/c'] +// ]; +// } + +// /** +// * @dataProvider providerRouteMatching +// */ +// public function testCanMatchRoute(string $method, string $path, string $url = null): void +// { +// $url ??= $path; +// $expected = null; + +// switch ($method) { +// case Http::REQUEST_METHOD_GET: +// $expected = Http::get($path); +// break; +// case Http::REQUEST_METHOD_POST: +// $expected = Http::post($path); +// break; +// case Http::REQUEST_METHOD_PUT: +// $expected = Http::put($path); +// break; +// case Http::REQUEST_METHOD_PATCH: +// $expected = Http::patch($path); +// break; +// case Http::REQUEST_METHOD_DELETE: +// $expected = Http::delete($path); +// break; +// } + +// $_SERVER['REQUEST_METHOD'] = $method; +// $_SERVER['REQUEST_URI'] = $url; + +// $this->assertEquals($expected, $this->http->match(new Request())); +// $this->assertEquals($expected, $this->http->getRoute()); +// } + +// public function testNoMismatchRoute(): void +// { +// $requests = [ +// [ +// 'path' => '/d/:id', +// 'url' => '/d/' +// ], +// [ +// 'path' => '/d/:id/e/:id2', +// 'url' => '/d/123/e/' +// ], +// [ +// 'path' => '/d/:id/e/:id2/f/:id3', +// 'url' => '/d/123/e/456/f/' +// ], +// ]; + +// foreach ($requests as $request) { +// Http::get($request['path']); + +// $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; +// $_SERVER['REQUEST_URI'] = $request['url']; + +// $route = $this->http->match(new Request(), fresh: true); + +// $this->assertEquals(null, $route); +// $this->assertEquals(null, $this->http->getRoute()); +// } +// } + +// public function testCanMatchFreshRoute(): void +// { +// $route1 = Http::get('/path1'); +// $route2 = Http::get('/path2'); + +// try { +// // Match first request +// $_SERVER['REQUEST_METHOD'] = 'HEAD'; +// $_SERVER['REQUEST_URI'] = '/path1'; +// $matched = $this->http->match(new Request()); +// $this->assertEquals($route1, $matched); +// $this->assertEquals($route1, $this->http->getRoute()); + +// // Second request match returns cached route +// $_SERVER['REQUEST_METHOD'] = 'HEAD'; +// $_SERVER['REQUEST_URI'] = '/path2'; +// $request2 = new Request(); +// $matched = $this->http->match($request2, fresh: false); +// $this->assertEquals($route1, $matched); +// $this->assertEquals($route1, $this->http->getRoute()); + +// // Fresh match returns new route +// $matched = $this->http->match($request2, fresh: true); +// $this->assertEquals($route2, $matched); +// $this->assertEquals($route2, $this->http->getRoute()); +// } catch (\Exception $e) { +// $this->fail($e->getMessage()); +// } +// } + +// public function testCanRunRequest(): void +// { +// // Test head requests + +// $method = (isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null; +// $uri = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : null; + +// $_SERVER['REQUEST_METHOD'] = 'HEAD'; +// $_SERVER['REQUEST_URI'] = '/path'; + +// Http::get('/path') +// ->dependency('response') +// ->action(function ($response) { +// $response->send('HELLO'); +// }); + +// \ob_start(); +// $this->http->run(new Request(), new Response(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $_SERVER['REQUEST_METHOD'] = $method; +// $_SERVER['REQUEST_URI'] = $uri; + +// $this->assertStringNotContainsString('HELLO', $result); +// } + +// public function testWildcardRoute(): void +// { +// $method = $_SERVER['REQUEST_METHOD'] ?? null; +// $uri = $_SERVER['REQUEST_URI'] ?? null; + +// $_SERVER['REQUEST_METHOD'] = 'GET'; +// $_SERVER['REQUEST_URI'] = '/unknown_path'; + +// Http::init() +// ->action(function () { +// $route = $this->http->getRoute(); +// Http::setResource('myRoute', fn () => $route); +// }); + + +// Http::wildcard() +// ->dependency('myRoute') +// ->dependency('response') +// ->action(function (mixed $myRoute, $response) { +// if ($myRoute == null) { +// $response->send('ROUTE IS NULL!'); +// } else { +// $response->send('HELLO'); +// } +// }); + +// \ob_start(); +// @$this->http->run(new Request(), new Response(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('HELLO', $result); + +// \ob_start(); +// $req = new Request(); +// $req = $req->setMethod('OPTIONS'); +// @$this->http->run($req, new Response(), '1'); +// $result = \ob_get_contents(); +// \ob_end_clean(); + +// $this->assertEquals('', $result); + +// $_SERVER['REQUEST_METHOD'] = $method; +// $_SERVER['REQUEST_URI'] = $uri; +// } +// } diff --git a/tests/RouteTest.php b/tests/RouteTest.php index 4a966b87..97a484e3 100755 --- a/tests/RouteTest.php +++ b/tests/RouteTest.php @@ -48,8 +48,7 @@ public function testCanSetAndGetGroups() public function testCanSetAndGetAction() { - $this->assertEquals(function (): void { - }, $this->route->getAction()); + $this->assertEquals(null, $this->route->getAction()); $this->route->action(fn () => 'hello world'); @@ -67,21 +66,6 @@ public function testCanGetAndSetParam() $this->assertCount(2, $this->route->getParams()); } - public function testCanInjectResources() - { - $this->assertEquals([], $this->route->getInjections()); - - $this->route - ->inject('user') - ->inject('time') - ->action(function () { - }); - - $this->assertCount(2, $this->route->getInjections()); - $this->assertEquals('user', $this->route->getInjections()['user']['name']); - $this->assertEquals('time', $this->route->getInjections()['time']['name']); - } - public function testCanSetAndGetLabels() { $this->assertEquals('default', $this->route->getLabel('key', 'default')); diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index 3fbdef51..6e91f301 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -1,38 +1,38 @@ client->call(Client::METHOD_GET, '/'); - $this->assertEquals('Hello World!', $response['body']); - } +// trait BaseTest +// { +// public function testResponse() +// { +// $response = $this->client->call(Client::METHOD_GET, '/'); +// $this->assertEquals('Hello World!', $response['body']); +// } - public function testResponseValue() - { - $response = $this->client->call(Client::METHOD_GET, '/value/123'); - $this->assertEquals('123', $response['body']); - } +// public function testResponseValue() +// { +// $response = $this->client->call(Client::METHOD_GET, '/value/123'); +// $this->assertEquals('123', $response['body']); +// } - public function testChunkResponse() - { - $response = $this->client->call(Client::METHOD_GET, '/chunked'); - $this->assertEquals('Hello World!', $response['body']); - } +// public function testChunkResponse() +// { +// $response = $this->client->call(Client::METHOD_GET, '/chunked'); +// $this->assertEquals('Hello World!', $response['body']); +// } - public function testRedirect() - { - $response = $this->client->call(Client::METHOD_GET, '/redirect'); - $this->assertEquals('Hello World!', $response['body']); - } +// public function testRedirect() +// { +// $response = $this->client->call(Client::METHOD_GET, '/redirect'); +// $this->assertEquals('Hello World!', $response['body']); +// } - public function testFile() - { - $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); - $this->assertEquals(204, $response['headers']['status-code']); - } -} +// public function testFile() +// { +// $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); +// $this->assertEquals(204, $response['headers']['status-code']); +// } +// } diff --git a/tests/e2e/ResponseFPMTest.php b/tests/e2e/ResponseFPMTest.php index 8a3cb4ff..388c9a93 100644 --- a/tests/e2e/ResponseFPMTest.php +++ b/tests/e2e/ResponseFPMTest.php @@ -1,17 +1,17 @@ client = new Client(); - } -} +// public function setUp(): void +// { +// $this->client = new Client(); +// } +// } diff --git a/tests/e2e/ResponseSwooleTest.php b/tests/e2e/ResponseSwooleTest.php index 0851554a..333cce33 100755 --- a/tests/e2e/ResponseSwooleTest.php +++ b/tests/e2e/ResponseSwooleTest.php @@ -1,23 +1,23 @@ client = new Client('http://swoole'); - } +// public function setUp(): void +// { +// $this->client = new Client('http://swoole'); +// } - public function testSwooleResources(): void - { - $response = $this->client->call(Client::METHOD_DELETE, '/swoole-test'); - $this->assertEquals('DELETE', $response['body']); - } -} +// public function testSwooleResources(): void +// { +// $response = $this->client->call(Client::METHOD_DELETE, '/swoole-test'); +// $this->assertEquals('DELETE', $response['body']); +// } +// } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 64bb3cfa..abe63a6f 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -13,20 +13,20 @@ error_reporting(E_ALL); Http::get('/') - ->inject('response') + ->dependency('response') ->action(function (Response $response) { $response->send('Hello World!'); }); Http::get('/value/:value') ->param('value', '', new Text(64)) - ->inject('response') + ->dependency('response') ->action(function (string $value, Response $response) { $response->send($value); }); Http::get('/chunked') - ->inject('response') + ->dependency('response') ->action(function (Response $response) { foreach (['Hello ', 'World!'] as $key => $word) { $response->chunk($word, $key == 1); @@ -34,13 +34,13 @@ }); Http::get('/redirect') - ->inject('response') + ->dependency('response') ->action(function (Response $response) { $response->redirect('/'); }); Http::get('/humans.txt') - ->inject('response') + ->dependency('response') ->action(function (Response $response) { $response->noContent(); }); diff --git a/tests/e2e/server-fpm.php b/tests/e2e/server-fpm.php index b886c118..8e889754 100644 --- a/tests/e2e/server-fpm.php +++ b/tests/e2e/server-fpm.php @@ -2,9 +2,10 @@ require_once __DIR__.'/init.php'; +use Utopia\DI\Container; use Utopia\Http\Adapter\FPM\Server; use Utopia\Http\Http; $server = new Server(); -$http = new Http($server, 'UTC'); +$http = new Http($server, new Container(), 'UTC'); $http->start(); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index e15e1be4..67ccbb75 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -4,14 +4,15 @@ use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; +use Utopia\DI\Container; use Utopia\Http\Adapter\Swoole\Server; use Utopia\Http\Http; use function Swoole\Coroutine\run; Http::delete('/swoole-test') - ->inject('swooleRequest') - ->inject('swooleResponse') + ->dependency('swooleRequest') + ->dependency('swooleResponse') ->action(function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $method = $swooleRequest->getMethod(); $swooleResponse->header('Content-Type', 'text/plain'); @@ -22,7 +23,7 @@ }); $server = new Server('0.0.0.0', '80'); -$http = new Http($server, 'UTC'); +$http = new Http($server, new Container(), 'UTC'); run(function () use ($http) { $http->start(); From 90cd4e638926cf5cfb819802df8304a88528d08d Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 4 Apr 2024 17:33:42 +0200 Subject: [PATCH 02/71] Fixed method mixup --- src/Http/Http.php | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 414e4f46..c3e23aca 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -508,7 +508,7 @@ public function start() try { foreach (self::$startHooks as $hook) { - $this->prepare($this->container, $hook, [], [])->dependency($hook); + $this->prepare($this->container, $hook, [], [])->inject($hook); } } catch(\Exception $e) { @@ -522,7 +522,7 @@ public function start() foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($this->container, $error, [], [])->dependency($error); + $this->prepare($this->container, $error, [], [])->inject($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -568,7 +568,7 @@ public function execute(Route $route, Request $request, Container $context): sta if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); } } } @@ -576,17 +576,17 @@ public function execute(Route $route, Request $request, Container $context): sta foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); } } } - $this->prepare($context, $route, $pathValues, $request->getParams())->dependency($route); + $this->prepare($context, $route, $pathValues, $request->getParams())->inject($route); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array($group, $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); } } } @@ -594,7 +594,7 @@ public function execute(Route $route, Request $request, Container $context): sta if ($route->getHook()) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array('*', $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->dependency($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); } } } @@ -610,7 +610,7 @@ public function execute(Route $route, Request $request, Container $context): sta foreach (self::$errors as $error) { // Group error hooks if (in_array($group, $error->getGroups())) { try { - $this->prepare($context, $error, $pathValues, $request->getParams())->dependency($error); + $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -621,7 +621,7 @@ public function execute(Route $route, Request $request, Container $context): sta foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($context, $error, $pathValues, $request->getParams())->dependency($error); + $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -703,11 +703,12 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a public function run(Container $context): static { $request = $context->get('request'); + $response = $context->get('response'); try { foreach (self::$requestHooks as $hook) { - $this->prepare($context, $hook)->dependency($hook); + $this->prepare($context, $hook)->inject($hook); } } catch(\Exception $e) { $dependency = new Dependency(); @@ -720,7 +721,7 @@ public function run(Container $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($context, $error)->dependency($hook); + $this->prepare($context, $error)->inject($hook); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } @@ -762,7 +763,7 @@ public function run(Container $context): static foreach (self::$options as $option) { // Group options hooks /** @var Hook $option */ if (in_array($group, $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->dependency($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option); } } } @@ -770,7 +771,7 @@ public function run(Container $context): static foreach (self::$options as $option) { // Global options hooks /** @var Hook $option */ if (in_array('*', $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->dependency($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option); } } } catch (\Throwable $e) { @@ -784,7 +785,7 @@ public function run(Container $context): static ) ; - $this->prepare($context, $error, [], $request->getParams())->dependency($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error); } } } @@ -812,14 +813,14 @@ public function run(Container $context): static foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks if (in_array($group, $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->dependency($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option); } } } foreach (self::$options as $option) { // Global options hooks if (in_array('*', $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->dependency($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option); } } } catch (\Throwable $e) { @@ -832,7 +833,7 @@ public function run(Container $context): static ) ; - $this->prepare($context, $error, [], $request->getParams())->dependency($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error); } } } @@ -846,7 +847,7 @@ public function run(Container $context): static ) ; - $this->prepare($context, $error, [], $request->getParams())->dependency($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error); } } } @@ -886,7 +887,7 @@ protected function validate(string $key, array $param, mixed $value, Container $ $dependency->dependency($injection); } - $validator = $context->dependency($dependency); + $validator = $context->inject($dependency); } if (!$validator instanceof Validator) { // is the validator object an instance of the Validator class From b263f105c611ef6e8ae7731dced4987f15c7fdf0 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 5 Apr 2024 00:26:51 +0200 Subject: [PATCH 03/71] Tests... --- composer.lock | 8 +- src/Http/Http.php | 49 +- src/Http/Router.php | 10 - tests/HttpTest.php | 1086 ++++++++++++++++++++--------------------- tests/k6/benchmark.js | 39 ++ 5 files changed, 613 insertions(+), 579 deletions(-) create mode 100644 tests/k6/benchmark.js diff --git a/composer.lock b/composer.lock index eec563a1..ee55abef 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "3f4390e2b64df56cfd2f46c831c30672ac4497c0" + "reference": "03bc1577ab777d0f09375dd8390f5fac059c562e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/3f4390e2b64df56cfd2f46c831c30672ac4497c0", - "reference": "3f4390e2b64df56cfd2f46c831c30672ac4497c0", + "url": "https://api.github.com/repos/utopia-php/di/zipball/03bc1577ab777d0f09375dd8390f5fac059c562e", + "reference": "03bc1577ab777d0f09375dd8390f5fac059c562e", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-04T13:13:18+00:00" + "time": "2024-04-04T15:49:21+00:00" } ], "packages-dev": [ diff --git a/src/Http/Http.php b/src/Http/Http.php index c3e23aca..215fd947 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -319,6 +319,24 @@ public static function setMode(string $value): void self::$mode = $value; } + /** + * Get Container + * + * @return Container + */ + public function getContainer(): Container + { + return $this->container; + } + + /** + * Set Container + */ + public function setContainer(Container $container): void + { + $this->container = $container; + } + /** * Get allow override * @@ -372,18 +390,6 @@ public static function isStage(): bool return self::MODE_TYPE_STAGE === self::$mode; } - /** - * Get Routes - * - * Get all application routes - * - * @return array - */ - public static function getRoutes(): array - { - return Router::getRoutes(); - } - /** * Add Route * @@ -493,7 +499,7 @@ public function start() ) ; - $this->run($request, $response, $context); + $this->run($context); }); $this->server->onStart(function ($server) { @@ -524,7 +530,7 @@ public function start() try { $this->prepare($this->container, $error, [], [])->inject($error); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } @@ -540,10 +546,9 @@ public function start() * Find matching route given current user request * * @param Request $request - * @param bool $fresh If true, will not match any cached route * @return null|Route */ - public function match(Request $request, bool $fresh = true): ?Route + public function match(Request $request): ?Route { $url = \parse_url($request->getURI(), PHP_URL_PATH); $method = $request->getMethod(); @@ -558,9 +563,8 @@ public function match(Request $request, bool $fresh = true): ?Route * @param Route $route * @param Request $request */ - public function execute(Route $route, Request $request, Container $context): static + protected function execute(Route $route, Request $request, Container $context): static { - $arguments = []; $groups = $route->getGroups(); $pathValues = $route->getPathValues($request); @@ -612,7 +616,7 @@ public function execute(Route $route, Request $request, Container $context): sta try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } @@ -623,7 +627,7 @@ public function execute(Route $route, Request $request, Container $context): sta try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } @@ -687,8 +691,9 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a $hook->setParamValue($key, $value); - return $context; } + + return $context; } /** @@ -723,7 +728,7 @@ public function run(Container $context): static try { $this->prepare($context, $error)->inject($hook); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } diff --git a/src/Http/Router.php b/src/Http/Router.php index d3324553..90c0fcf2 100644 --- a/src/Http/Router.php +++ b/src/Http/Router.php @@ -32,16 +32,6 @@ class Router */ protected static array $params = []; - /** - * Get all registered routes. - * - * @return array - */ - public static function getRoutes(): array - { - return self::$routes; - } - /** * Get allow override * diff --git a/tests/HttpTest.php b/tests/HttpTest.php index 31b51148..95bfa7cb 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -1,545 +1,545 @@ http = new Http(new Server(), new Container(), 'Asia/Tel_Aviv'); -// $this->saveRequest(); -// } - -// public function tearDown(): void -// { -// $this->http = null; -// $this->restoreRequest(); -// } - -// protected function saveRequest(): void -// { -// $this->method = $_SERVER['REQUEST_METHOD'] ?? null; -// $this->uri = $_SERVER['REQUEST_URI'] ?? null; -// } - -// protected function restoreRequest(): void -// { -// $_SERVER['REQUEST_METHOD'] = $this->method; -// $_SERVER['REQUEST_URI'] = $this->uri; -// } - -// public function testCanGetDifferentModes(): void -// { -// $this->assertEmpty(Http::getMode()); -// $this->assertFalse(Http::isProduction()); -// $this->assertFalse(Http::isDevelopment()); -// $this->assertFalse(Http::isStage()); - -// Http::setMode(Http::MODE_TYPE_PRODUCTION); - -// $this->assertEquals(Http::MODE_TYPE_PRODUCTION, Http::getMode()); -// $this->assertTrue(Http::isProduction()); -// $this->assertFalse(Http::isDevelopment()); -// $this->assertFalse(Http::isStage()); - -// Http::setMode(Http::MODE_TYPE_DEVELOPMENT); - -// $this->assertEquals(Http::MODE_TYPE_DEVELOPMENT, Http::getMode()); -// $this->assertFalse(Http::isProduction()); -// $this->assertTrue(Http::isDevelopment()); -// $this->assertFalse(Http::isStage()); - -// Http::setMode(Http::MODE_TYPE_STAGE); - -// $this->assertEquals(Http::MODE_TYPE_STAGE, Http::getMode()); -// $this->assertFalse(Http::isProduction()); -// $this->assertFalse(Http::isDevelopment()); -// $this->assertTrue(Http::isStage()); -// } - -// public function testCanExecuteRoute(): void -// { -// Http::setResource('rand', fn () => rand()); -// $resource = $this->http->getResource('rand', '1'); - -// $this->http -// ->error() -// ->dependency('error') -// ->action(function ($error) { -// echo 'error: ' . $error->getMessage(); -// }); - -// // Default Params -// $route = new Route('GET', '/path'); - -// $route -// ->param('x', 'x-def', new Text(200), 'x param', true) -// ->param('y', 'y-def', new Text(200), 'y param', true) -// ->action(function ($x, $y) { -// echo $x . '-' . $y; -// }); - -// \ob_start(); -// $this->http->execute($route, new Request(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// // With Params -// $resource = $this->http->getResource('rand', '1'); -// $route = new Route('GET', '/path'); - -// $route -// ->param('x', 'x-def', new Text(200), 'x param', true) -// ->param('y', 'y-def', new Text(200), 'y param', true) -// ->dependency('rand') -// ->param('z', 'z-def', function ($rand) { -// echo $rand . '-'; - -// return new Text(200); -// }, 'z param', true, ['rand']) -// ->action(function ($x, $y, $z, $rand) { -// echo $x . '-', $y; -// }); - -// \ob_start(); -// $request = new UtopiaFPMRequestTest(); -// $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); -// $this->http->execute($route, $request, '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals($resource . '-param-x-param-y', $result); - -// // With Error -// $resource = $this->http->getResource('rand', '1'); -// $route = new Route('GET', '/path'); - -// $route -// ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) -// ->param('y', 'y-def', new Text(1, min: 0), 'y param', false) -// ->action(function ($x, $y) { -// echo $x . '-', $y; -// }); - -// \ob_start(); -// $request = new UtopiaFPMRequestTest(); -// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); -// $this->http->execute($route, $request, '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); - -// // With Hooks -// $resource = $this->http->getResource('rand', '1'); -// $this->http -// ->init() -// ->dependency('rand') -// ->action(function ($rand) { -// echo 'init-' . $rand . '-'; -// }); - -// $this->http -// ->shutdown() -// ->action(function () { -// echo '-shutdown'; -// }); - -// $this->http -// ->init() -// ->groups(['api']) -// ->action(function () { -// echo '(init-api)-'; -// }); - -// $this->http -// ->shutdown() -// ->groups(['api']) -// ->action(function () { -// echo '-(shutdown-api)'; -// }); - -// $this->http -// ->init() -// ->groups(['homepage']) -// ->action(function () { -// echo '(init-homepage)-'; -// }); - -// $this->http -// ->shutdown() -// ->groups(['homepage']) -// ->action(function () { -// echo '-(shutdown-homepage)'; -// }); - -// $route = new Route('GET', '/path'); - -// $route -// ->groups(['api']) -// ->param('x', 'x-def', new Text(200), 'x param', false) -// ->param('y', 'y-def', new Text(200), 'y param', false) -// ->action(function ($x, $y) { -// echo $x . '-', $y; -// }); - -// $homepage = new Route('GET', '/path'); - -// $homepage -// ->groups(['homepage']) -// ->param('x', 'x-def', new Text(200), 'x param', false) -// ->param('y', 'y-def', new Text(200), 'y param', false) -// ->action(function ($x, $y) { -// echo $x . '*', $y; -// }); - -// \ob_start(); -// $request = new UtopiaFPMRequestTest(); -// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); -// $this->http->execute($route, $request, '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); - -// $resource = $this->http->getResource('rand', '1'); -// \ob_start(); -// $request = new UtopiaFPMRequestTest(); -// $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); -// $this->http->execute($homepage, $request, '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('init-' . $resource . '-(init-homepage)-param-x*param-y-(shutdown-homepage)-shutdown', $result); -// } - -// public function testCanAddAndExecuteHooks() -// { -// $this->http -// ->init() -// ->action(function () { -// echo '(init)-'; -// }); - -// $this->http -// ->shutdown() -// ->action(function () { -// echo '-(shutdown)'; -// }); - -// // Default Params -// $route = new Route('GET', '/path'); -// $route -// ->param('x', 'x-def', new Text(200), 'x param', true) -// ->action(function ($x) { -// echo $x; -// }); - -// \ob_start(); -// $this->http->execute($route, new Request(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('(init)-x-def-(shutdown)', $result); - -// // Default Params -// $route = new Route('GET', '/path'); -// $route -// ->param('x', 'x-def', new Text(200), 'x param', true) -// ->hook(false) -// ->action(function ($x) { -// echo $x; -// }); - -// \ob_start(); -// $this->http->execute($route, new Request(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('x-def', $result); -// } - -// public function testAllowRouteOverrides() -// { -// Http::setAllowOverride(false); -// $this->assertFalse(Http::getAllowOverride()); -// Http::get('/')->action(function () { -// echo 'Hello first'; -// }); - -// try { -// Http::get('/')->action(function () { -// echo 'Hello second'; -// }); -// $this->fail('Failed to throw exception'); -// } catch (\Exception $e) { -// // Threw exception as expected -// $this->assertEquals('Route for (GET:) already registered.', $e->getMessage()); -// } - -// // Test success -// Http::setAllowOverride(true); -// $this->assertTrue(Http::getAllowOverride()); -// Http::get('/')->action(function () { -// echo 'Hello first'; -// }); - -// Http::get('/')->action(function () { -// echo 'Hello second'; -// }); -// } - -// public function testCanHookThrowExceptions() -// { -// $this->http -// ->init() -// ->param('y', '', new Text(5), 'y param', false) -// ->action(function ($y) { -// echo '(init)-' . $y . '-'; -// }); - -// $this->http -// ->error() -// ->dependency('error') -// ->action(function ($error) { -// echo 'error-' . $error->getMessage(); -// }); - -// $this->http -// ->shutdown() -// ->action(function () { -// echo '-(shutdown)'; -// }); - -// // param not provided for init -// $route = new Route('GET', '/path'); -// $route -// ->param('x', 'x-def', new Text(200), 'x param', true) -// ->action(function ($x) { -// echo $x; -// }); - -// \ob_start(); -// $this->http->execute($route, new Request(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('error-Param "y" is not optional.', $result); - -// \ob_start(); -// $_GET['y'] = 'y-def'; -// $this->http->execute($route, new Request(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('(init)-y-def-x-def-(shutdown)', $result); -// } - -// public function testCanSetRoute() -// { -// $route = new Route('GET', '/path'); - -// $this->assertEquals($this->http->getRoute(), null); -// $this->http->setRoute($route); -// $this->assertEquals($this->http->getRoute(), $route); -// } - -// public function providerRouteMatching(): array -// { -// return [ -// 'GET request' => [Http::REQUEST_METHOD_GET, '/path1'], -// 'GET request on different route' => [Http::REQUEST_METHOD_GET, '/path2'], -// 'GET request with trailing slash #1' => [Http::REQUEST_METHOD_GET, '/path3', '/path3/'], -// 'GET request with trailing slash #2' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3/'], -// 'GET request with trailing slash #3' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3'], -// 'POST request' => [Http::REQUEST_METHOD_POST, '/path1'], -// 'PUT request' => [Http::REQUEST_METHOD_PUT, '/path1'], -// 'PATCH request' => [Http::REQUEST_METHOD_PATCH, '/path1'], -// 'DELETE request' => [Http::REQUEST_METHOD_DELETE, '/path1'], -// '1 separators' => [Http::REQUEST_METHOD_GET, '/a/'], -// '2 separators' => [Http::REQUEST_METHOD_GET, '/a/b'], -// '3 separators' => [Http::REQUEST_METHOD_GET, '/a/b/c'] -// ]; -// } - -// /** -// * @dataProvider providerRouteMatching -// */ -// public function testCanMatchRoute(string $method, string $path, string $url = null): void -// { -// $url ??= $path; -// $expected = null; - -// switch ($method) { -// case Http::REQUEST_METHOD_GET: -// $expected = Http::get($path); -// break; -// case Http::REQUEST_METHOD_POST: -// $expected = Http::post($path); -// break; -// case Http::REQUEST_METHOD_PUT: -// $expected = Http::put($path); -// break; -// case Http::REQUEST_METHOD_PATCH: -// $expected = Http::patch($path); -// break; -// case Http::REQUEST_METHOD_DELETE: -// $expected = Http::delete($path); -// break; -// } - -// $_SERVER['REQUEST_METHOD'] = $method; -// $_SERVER['REQUEST_URI'] = $url; - -// $this->assertEquals($expected, $this->http->match(new Request())); -// $this->assertEquals($expected, $this->http->getRoute()); -// } - -// public function testNoMismatchRoute(): void -// { -// $requests = [ -// [ -// 'path' => '/d/:id', -// 'url' => '/d/' -// ], -// [ -// 'path' => '/d/:id/e/:id2', -// 'url' => '/d/123/e/' -// ], -// [ -// 'path' => '/d/:id/e/:id2/f/:id3', -// 'url' => '/d/123/e/456/f/' -// ], -// ]; - -// foreach ($requests as $request) { -// Http::get($request['path']); - -// $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; -// $_SERVER['REQUEST_URI'] = $request['url']; - -// $route = $this->http->match(new Request(), fresh: true); - -// $this->assertEquals(null, $route); -// $this->assertEquals(null, $this->http->getRoute()); -// } -// } - -// public function testCanMatchFreshRoute(): void -// { -// $route1 = Http::get('/path1'); -// $route2 = Http::get('/path2'); - -// try { -// // Match first request -// $_SERVER['REQUEST_METHOD'] = 'HEAD'; -// $_SERVER['REQUEST_URI'] = '/path1'; -// $matched = $this->http->match(new Request()); -// $this->assertEquals($route1, $matched); -// $this->assertEquals($route1, $this->http->getRoute()); - -// // Second request match returns cached route -// $_SERVER['REQUEST_METHOD'] = 'HEAD'; -// $_SERVER['REQUEST_URI'] = '/path2'; -// $request2 = new Request(); -// $matched = $this->http->match($request2, fresh: false); -// $this->assertEquals($route1, $matched); -// $this->assertEquals($route1, $this->http->getRoute()); - -// // Fresh match returns new route -// $matched = $this->http->match($request2, fresh: true); -// $this->assertEquals($route2, $matched); -// $this->assertEquals($route2, $this->http->getRoute()); -// } catch (\Exception $e) { -// $this->fail($e->getMessage()); -// } -// } - -// public function testCanRunRequest(): void -// { -// // Test head requests - -// $method = (isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null; -// $uri = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : null; - -// $_SERVER['REQUEST_METHOD'] = 'HEAD'; -// $_SERVER['REQUEST_URI'] = '/path'; - -// Http::get('/path') -// ->dependency('response') -// ->action(function ($response) { -// $response->send('HELLO'); -// }); - -// \ob_start(); -// $this->http->run(new Request(), new Response(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $_SERVER['REQUEST_METHOD'] = $method; -// $_SERVER['REQUEST_URI'] = $uri; - -// $this->assertStringNotContainsString('HELLO', $result); -// } - -// public function testWildcardRoute(): void -// { -// $method = $_SERVER['REQUEST_METHOD'] ?? null; -// $uri = $_SERVER['REQUEST_URI'] ?? null; - -// $_SERVER['REQUEST_METHOD'] = 'GET'; -// $_SERVER['REQUEST_URI'] = '/unknown_path'; - -// Http::init() -// ->action(function () { -// $route = $this->http->getRoute(); -// Http::setResource('myRoute', fn () => $route); -// }); - - -// Http::wildcard() -// ->dependency('myRoute') -// ->dependency('response') -// ->action(function (mixed $myRoute, $response) { -// if ($myRoute == null) { -// $response->send('ROUTE IS NULL!'); -// } else { -// $response->send('HELLO'); -// } -// }); - -// \ob_start(); -// @$this->http->run(new Request(), new Response(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('HELLO', $result); - -// \ob_start(); -// $req = new Request(); -// $req = $req->setMethod('OPTIONS'); -// @$this->http->run($req, new Response(), '1'); -// $result = \ob_get_contents(); -// \ob_end_clean(); - -// $this->assertEquals('', $result); - -// $_SERVER['REQUEST_METHOD'] = $method; -// $_SERVER['REQUEST_URI'] = $uri; -// } -// } +namespace Utopia\Http; + +use PHPUnit\Framework\TestCase; +use Utopia\DI\Container; +use Utopia\DI\Dependency; +use Utopia\Http\Tests\UtopiaFPMRequestTest; +use Utopia\Http\Validator\Text; +use Utopia\Http\Adapter\FPM\Request; +use Utopia\Http\Adapter\FPM\Response; +use Utopia\Http\Adapter\FPM\Server; + +class HttpTest extends TestCase +{ + protected ?Http $http; + + protected Container $context; + + protected ?string $method; + + protected ?string $uri; + + public function setUp(): void + { + Http::reset(); + $this->context = new Container(); + $this->http = new Http(new Server(), $this->context, 'Asia/Tel_Aviv'); + $this->saveRequest(); + } + + public function tearDown(): void + { + $this->http = null; + $this->restoreRequest(); + } + + protected function saveRequest(): void + { + $this->method = $_SERVER['REQUEST_METHOD'] ?? null; + $this->uri = $_SERVER['REQUEST_URI'] ?? null; + } + + protected function restoreRequest(): void + { + $_SERVER['REQUEST_METHOD'] = $this->method; + $_SERVER['REQUEST_URI'] = $this->uri; + } + + public function testCanGetDifferentModes(): void + { + $this->assertEmpty(Http::getMode()); + $this->assertFalse(Http::isProduction()); + $this->assertFalse(Http::isDevelopment()); + $this->assertFalse(Http::isStage()); + + Http::setMode(Http::MODE_TYPE_PRODUCTION); + + $this->assertEquals(Http::MODE_TYPE_PRODUCTION, Http::getMode()); + $this->assertTrue(Http::isProduction()); + $this->assertFalse(Http::isDevelopment()); + $this->assertFalse(Http::isStage()); + + Http::setMode(Http::MODE_TYPE_DEVELOPMENT); + + $this->assertEquals(Http::MODE_TYPE_DEVELOPMENT, Http::getMode()); + $this->assertFalse(Http::isProduction()); + $this->assertTrue(Http::isDevelopment()); + $this->assertFalse(Http::isStage()); + + Http::setMode(Http::MODE_TYPE_STAGE); + + $this->assertEquals(Http::MODE_TYPE_STAGE, Http::getMode()); + $this->assertFalse(Http::isProduction()); + $this->assertFalse(Http::isDevelopment()); + $this->assertTrue(Http::isStage()); + } + + public function testCanExecuteRoute(): void + { + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error: ' . $error->getMessage(); + }); + + // Default Params + $route = new Route('GET', '/path'); + + $route + ->param('x', 'x-def', new Text(200), 'x param', true) + ->param('y', 'y-def', new Text(200), 'y param', true) + ->action(function ($x, $y) { + echo $x . '-' . $y; + }); + + \ob_start(); + $this->http->execute($route, new Request(), new Container()); + $result = \ob_get_contents(); + \ob_end_clean(); + + // With Params + $route = new Route('GET', '/path'); + + $route + ->param('x', 'x-def', new Text(200), 'x param', true) + ->param('y', 'y-def', new Text(200), 'y param', true) + ->dependency('rand') + ->param('z', 'z-def', function ($rand) { + echo $rand . '-'; + + return new Text(200); + }, 'z param', true, ['rand']) + ->action(function ($x, $y, $z, $rand) { + echo $x . '-', $y; + }); + + \ob_start(); + $request = new UtopiaFPMRequestTest(); + $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); + $this->http->execute($route, $request, $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + // $this->assertEquals($resource . '-param-x-param-y', $result); + + // With Error + $route = new Route('GET', '/path'); + + $route + ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) + ->param('y', 'y-def', new Text(1, min: 0), 'y param', false) + ->action(function ($x, $y) { + echo $x . '-', $y; + }); + + \ob_start(); + $request = new UtopiaFPMRequestTest(); + $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); + $this->http->execute($route, $request, $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); + + // With Hooks + $this->http + ->init() + ->dependency('rand') + ->action(function ($rand) { + echo 'init-' . $rand . '-'; + }); + + $this->http + ->shutdown() + ->action(function () { + echo '-shutdown'; + }); + + $this->http + ->init() + ->groups(['api']) + ->action(function () { + echo '(init-api)-'; + }); + + $this->http + ->shutdown() + ->groups(['api']) + ->action(function () { + echo '-(shutdown-api)'; + }); + + $this->http + ->init() + ->groups(['homepage']) + ->action(function () { + echo '(init-homepage)-'; + }); + + $this->http + ->shutdown() + ->groups(['homepage']) + ->action(function () { + echo '-(shutdown-homepage)'; + }); + + $route = new Route('GET', '/path'); + + $route + ->groups(['api']) + ->param('x', 'x-def', new Text(200), 'x param', false) + ->param('y', 'y-def', new Text(200), 'y param', false) + ->action(function ($x, $y) { + echo $x . '-', $y; + }); + + $homepage = new Route('GET', '/path'); + + $homepage + ->groups(['homepage']) + ->param('x', 'x-def', new Text(200), 'x param', false) + ->param('y', 'y-def', new Text(200), 'y param', false) + ->action(function ($x, $y) { + echo $x . '*', $y; + }); + + \ob_start(); + $request = new UtopiaFPMRequestTest(); + $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); + $this->http->execute($route, $request, $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); + + $resource = $this->http->getResource('rand', $this->context); + \ob_start(); + $request = new UtopiaFPMRequestTest(); + $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); + $this->http->execute($homepage, $request, $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('init-' . $resource . '-(init-homepage)-param-x*param-y-(shutdown-homepage)-shutdown', $result); + } + + public function testCanAddAndExecuteHooks() + { + $this->http + ->init() + ->action(function () { + echo '(init)-'; + }); + + $this->http + ->shutdown() + ->action(function () { + echo '-(shutdown)'; + }); + + // Default Params + $route = new Route('GET', '/path'); + $route + ->param('x', 'x-def', new Text(200), 'x param', true) + ->action(function ($x) { + echo $x; + }); + + \ob_start(); + $this->http->execute($route, new Request(), $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('(init)-x-def-(shutdown)', $result); + + // Default Params + $route = new Route('GET', '/path'); + $route + ->param('x', 'x-def', new Text(200), 'x param', true) + ->hook(false) + ->action(function ($x) { + echo $x; + }); + + \ob_start(); + $this->http->execute($route, new Request(), $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('x-def', $result); + } + + public function testAllowRouteOverrides() + { + Http::setAllowOverride(false); + $this->assertFalse(Http::getAllowOverride()); + Http::get('/')->action(function () { + echo 'Hello first'; + }); + + try { + Http::get('/')->action(function () { + echo 'Hello second'; + }); + $this->fail('Failed to throw exception'); + } catch (\Exception $e) { + // Threw exception as expected + $this->assertEquals('Route for (GET:) already registered.', $e->getMessage()); + } + + // Test success + Http::setAllowOverride(true); + $this->assertTrue(Http::getAllowOverride()); + Http::get('/')->action(function () { + echo 'Hello first'; + }); + + Http::get('/')->action(function () { + echo 'Hello second'; + }); + } + + public function testCanHookThrowExceptions() + { + $this->http + ->init() + ->param('y', '', new Text(5), 'y param', false) + ->action(function ($y) { + echo '(init)-' . $y . '-'; + }); + + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error-' . $error->getMessage(); + }); + + $this->http + ->shutdown() + ->action(function () { + echo '-(shutdown)'; + }); + + // param not provided for init + $route = new Route('GET', '/path'); + $route + ->param('x', 'x-def', new Text(200), 'x param', true) + ->action(function ($x) { + echo $x; + }); + + \ob_start(); + $this->http->execute($route, new Request(), $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('error-Param "y" is not optional.', $result); + + \ob_start(); + $_GET['y'] = 'y-def'; + $this->http->execute($route, new Request(), $this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('(init)-y-def-x-def-(shutdown)', $result); + } + + public function testCanSetRoute() + { + $route = new Dependency(); + $route + ->setName('route') + ->setCallback(fn () => null) + ; + + $this->http->getContainer()->set($route); + + $this->assertEquals($this->http->getContainer()->get('route'), null); + + $og = new Route('GET', '/path'); + $route = new Dependency(); + $route + ->setName('route') + ->setCallback(fn () => $og) + ; + + $this->http->getContainer()->set($route); + + $this->assertEquals($this->http->getContainer()->get('route'), $og); + } + + public function providerRouteMatching(): array + { + return [ + 'GET request' => [Http::REQUEST_METHOD_GET, '/path1'], + 'GET request on different route' => [Http::REQUEST_METHOD_GET, '/path2'], + 'GET request with trailing slash #1' => [Http::REQUEST_METHOD_GET, '/path3', '/path3/'], + 'GET request with trailing slash #2' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3/'], + 'GET request with trailing slash #3' => [Http::REQUEST_METHOD_GET, '/path3/', '/path3'], + 'POST request' => [Http::REQUEST_METHOD_POST, '/path1'], + 'PUT request' => [Http::REQUEST_METHOD_PUT, '/path1'], + 'PATCH request' => [Http::REQUEST_METHOD_PATCH, '/path1'], + 'DELETE request' => [Http::REQUEST_METHOD_DELETE, '/path1'], + '1 separators' => [Http::REQUEST_METHOD_GET, '/a/'], + '2 separators' => [Http::REQUEST_METHOD_GET, '/a/b'], + '3 separators' => [Http::REQUEST_METHOD_GET, '/a/b/c'] + ]; + } + + /** + * @dataProvider providerRouteMatching + */ + public function testCanMatchRoute(string $method, string $path, string $url = null): void + { + $url ??= $path; + $expected = null; + + switch ($method) { + case Http::REQUEST_METHOD_GET: + $expected = Http::get($path); + break; + case Http::REQUEST_METHOD_POST: + $expected = Http::post($path); + break; + case Http::REQUEST_METHOD_PUT: + $expected = Http::put($path); + break; + case Http::REQUEST_METHOD_PATCH: + $expected = Http::patch($path); + break; + case Http::REQUEST_METHOD_DELETE: + $expected = Http::delete($path); + break; + } + + $_SERVER['REQUEST_METHOD'] = $method; + $_SERVER['REQUEST_URI'] = $url; + + $route = $this->http->match(new Request()); + $this->assertEquals($expected, $route); + } + + public function testNoMismatchRoute(): void + { + $requests = [ + [ + 'path' => '/d/:id', + 'url' => '/d/' + ], + [ + 'path' => '/d/:id/e/:id2', + 'url' => '/d/123/e/' + ], + [ + 'path' => '/d/:id/e/:id2/f/:id3', + 'url' => '/d/123/e/456/f/' + ], + ]; + + foreach ($requests as $request) { + Http::get($request['path']); + +var_dump($request['url']); + $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; + $_SERVER['REQUEST_URI'] = $request['url']; + + $context = new Container(); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(fn () => new Request()); + + $response = new Dependency(); + $response + ->setName('response') + ->setCallback(fn () => new Response()); + + $context + ->set($request) + ->set($response) + ; + + $this->http->run($context); + + $this->assertEquals(null, $context->get('route')); + } + } + + public function testCanRunRequest(): void + { + // Test head requests + + $method = (isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null; + $uri = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : null; + + $_SERVER['REQUEST_METHOD'] = 'HEAD'; + $_SERVER['REQUEST_URI'] = '/path'; + + Http::get('/path') + ->dependency('response') + ->action(function ($response) { + $response->send('HELLO'); + }); + + \ob_start(); + $this->http->run($this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $_SERVER['REQUEST_METHOD'] = $method; + $_SERVER['REQUEST_URI'] = $uri; + + $this->assertStringNotContainsString('HELLO', $result); + } + + public function testWildcardRoute(): void + { + $method = $_SERVER['REQUEST_METHOD'] ?? null; + $uri = $_SERVER['REQUEST_URI'] ?? null; + + $_SERVER['REQUEST_METHOD'] = 'GET'; + $_SERVER['REQUEST_URI'] = '/unknown_path'; + + Http::init() + ->action(function () { + $route = $this->http->getRoute(); + Http::setResource('myRoute', fn () => $route); + }); + + + Http::wildcard() + ->dependency('myRoute') + ->dependency('response') + ->action(function (mixed $myRoute, $response) { + if ($myRoute == null) { + $response->send('ROUTE IS NULL!'); + } else { + $response->send('HELLO'); + } + }); + + \ob_start(); + @$this->http->run($this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('HELLO', $result); + + \ob_start(); + $req = new Request(); + $req = $req->setMethod('OPTIONS'); + @$this->http->run($this->context); + $result = \ob_get_contents(); + \ob_end_clean(); + + $this->assertEquals('', $result); + + $_SERVER['REQUEST_METHOD'] = $method; + $_SERVER['REQUEST_URI'] = $uri; + } +} diff --git a/tests/k6/benchmark.js b/tests/k6/benchmark.js new file mode 100644 index 00000000..a78c434b --- /dev/null +++ b/tests/k6/benchmark.js @@ -0,0 +1,39 @@ +import http from 'k6/http'; +import { check } from 'k6'; +import { Counter } from 'k6/metrics'; + +// A simple counter for http requests +export const requests = new Counter('http_reqs'); + +// you can specify stages of your test (ramp up/down patterns) through the options object +// target is the number of VUs you are aiming for + +export const options = { + scenarios: { + contacts: { + executor: 'ramping-arrival-rate', + preAllocatedVUs: 20, + timeUnit: '1s', + startRate: 50, + stages: [ + { target: 1000, duration: '30s' }, // linearly go from 50 iters/s to 200 iters/s for 30s + // { target: 500, duration: '0' }, // instantly jump to 500 iters/s + // { target: 500, duration: '10m' }, // continue with 500 iters/s for 10 minutes + ], + }, + }, + }; + +export default function () { + const config = { + headers: { + 'X-Appwrite-Key': '24356eb021863f81eb7dd77c7750304d0464e141cad6e9a8befa1f7d2b066fde190df3dab1e8d2639dbb82ee848da30501424923f4cd80d887ee40ad77ded62763ee489448523f6e39667f290f9a54b2ab8fad131a0bc985e6c0f760015f7f3411e40626c75646bb19d2bb2f7bf2f63130918220a206758cbc48845fd725a695', + 'X-Appwrite-Project': '60479fe35d95d' + }} + + const resDb = http.get('http://localhost:9501/', config); + + check(resDb, { + 'status is 200': (r) => r.status === 200, + }); +} \ No newline at end of file From 654a9170b36b4af03dfdcaa2f94bc6d616bd512e Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 5 Apr 2024 00:45:25 +0200 Subject: [PATCH 04/71] Fixed test --- src/Http/Http.php | 1 - tests/HttpTest.php | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 215fd947..a05f627c 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -711,7 +711,6 @@ public function run(Container $context): static $response = $context->get('response'); try { - foreach (self::$requestHooks as $hook) { $this->prepare($context, $hook)->inject($hook); } diff --git a/tests/HttpTest.php b/tests/HttpTest.php index 95bfa7cb..6aba7101 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -443,7 +443,6 @@ public function testNoMismatchRoute(): void foreach ($requests as $request) { Http::get($request['path']); -var_dump($request['url']); $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; $_SERVER['REQUEST_URI'] = $request['url']; @@ -487,7 +486,26 @@ public function testCanRunRequest(): void }); \ob_start(); - $this->http->run($this->context); + + + $context = new Container(); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(fn () => new Request()); + + $response = new Dependency(); + $response + ->setName('response') + ->setCallback(fn () => new Response()); + + $context + ->set($request) + ->set($response) + ; + + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); From 241aebf69e8fdf043553949e04fea7c8b1e86f52 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 5 Apr 2024 22:06:20 +0200 Subject: [PATCH 05/71] Fixed a few more tests --- src/Http/Adapter/FPM/Server.php | 1 - src/Http/Adapter/Swoole/Server.php | 1 - src/Http/Http.php | 10 ++--- tests/HttpTest.php | 66 +++++++++++++++++++++++++----- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/Http/Adapter/FPM/Server.php b/src/Http/Adapter/FPM/Server.php index 797459a0..46e54124 100755 --- a/src/Http/Adapter/FPM/Server.php +++ b/src/Http/Adapter/FPM/Server.php @@ -3,7 +3,6 @@ namespace Utopia\Http\Adapter\FPM; use Utopia\Http\Adapter; -use Utopia\Http\Http; class Server extends Adapter { diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 96035ce6..a12d6e85 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -7,7 +7,6 @@ use Swoole\Coroutine\Http\Server as SwooleServer; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; -use Utopia\Http\Http; use function Swoole\Coroutine\run; diff --git a/src/Http/Http.php b/src/Http/Http.php index a05f627c..22a2e536 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -845,11 +845,11 @@ public function run(Container $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $this->container->set($dependency - ->setName('error') - ->setCallback(fn () => $e) - ) - ; + $dependency + ->setName('error') + ->setCallback(fn () => new Exception('Not Found', 404)); + + $context->set($dependency); $this->prepare($context, $error, [], $request->getParams())->inject($error); } diff --git a/tests/HttpTest.php b/tests/HttpTest.php index 6aba7101..e66838e5 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -78,6 +78,23 @@ public function testCanGetDifferentModes(): void public function testCanExecuteRoute(): void { + $context = new Container(); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(fn () => new Request()); + + $response = new Dependency(); + $response + ->setName('response') + ->setCallback(fn () => new Response()); + + $context + ->set($request) + ->set($response) + ; + $this->http ->error() ->dependency('error') @@ -86,7 +103,7 @@ public function testCanExecuteRoute(): void }); // Default Params - $route = new Route('GET', '/path'); + $route = $this->http->addRoute('GET', '/path'); $route ->param('x', 'x-def', new Text(200), 'x param', true) @@ -96,12 +113,43 @@ public function testCanExecuteRoute(): void }); \ob_start(); - $this->http->execute($route, new Request(), new Container()); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); + } - // With Params - $route = new Route('GET', '/path'); + public function testCanExecuteRouteWithParams(): void + { + $_SERVER['REQUEST_URI'] = '/path'; + $context = new Container(); + $requestObj = new UtopiaFPMRequestTest(); + $responseObj = new Response(); + + $requestObj::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(fn () => $requestObj); + + $response = new Dependency(); + $response + ->setName('response') + ->setCallback(fn () => $responseObj); + + $context + ->set($request) + ->set($response) + ; + + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error: ' . $error->getMessage(); + }); + + $route = $this->http->addRoute('GET', '/path'); $route ->param('x', 'x-def', new Text(200), 'x param', true) @@ -117,16 +165,14 @@ public function testCanExecuteRoute(): void }); \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); - $this->http->execute($route, $request, $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - - // $this->assertEquals($resource . '-param-x-param-y', $result); + $resource = 'dasdasd'; + $this->assertEquals($resource . '-param-x-param-y', $result); // With Error - $route = new Route('GET', '/path'); + $route = $this->http->addRoute('GET', '/path'); $route ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) From 4351e83e92c819324fcfc0b843acd8e123114cf4 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 5 Apr 2024 22:10:12 +0200 Subject: [PATCH 06/71] Update benchmark --- tests/k6/benchmark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/k6/benchmark.js b/tests/k6/benchmark.js index a78c434b..9807241b 100644 --- a/tests/k6/benchmark.js +++ b/tests/k6/benchmark.js @@ -16,7 +16,7 @@ export const options = { timeUnit: '1s', startRate: 50, stages: [ - { target: 1000, duration: '30s' }, // linearly go from 50 iters/s to 200 iters/s for 30s + { target: 10000, duration: '1m' }, // linearly go from 50 iters/s to 200 iters/s for 30s // { target: 500, duration: '0' }, // instantly jump to 500 iters/s // { target: 500, duration: '10m' }, // continue with 500 iters/s for 10 minutes ], From f5abb5ffbf237ca3cf1b8a474f9baca8373007e4 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sun, 7 Apr 2024 06:55:33 +0200 Subject: [PATCH 07/71] Updated benchmark --- docker-compose.yml | 2 +- src/Http/Adapter/Swoole/Server.php | 19 ++++++++++++- tests/e2e/init.php | 17 ++++++++++-- tests/e2e/server-swoole.php | 27 ++++++++++++++----- tests/k6/benchmark.js | 43 +++++++++++++++++------------- 5 files changed, 80 insertions(+), 28 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0c4e0011..64a13adf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: context: . dockerfile: Dockerfile.swoole ports: - - "9501:80" + - "9500:80" volumes: - ./src:/usr/src/code/src - ./tests:/usr/src/code/tests diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index a12d6e85..c20045e8 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -16,9 +16,24 @@ class Server extends Adapter public function __construct(string $host, string $port = null, array $settings = []) { + $workerNumber = swoole_cpu_num() * 6; $this->server = new SwooleServer($host, $port); $this->server->set(\array_merge($settings, [ - 'enable_coroutine' => true + 'open_http2_protocol' => true, + // 'http_compression' => true, + // 'http_compression_level' => 6, + + // Server + // 'log_level' => 2, + 'dispatch_mode' => 3, + 'worker_num' => $workerNumber, + 'reactor_num' => swoole_cpu_num() * 2, + 'task_worker_num' => $workerNumber, + 'open_cpu_affinity' => true, + + // Coroutine + 'enable_coroutine' => true, + 'max_coroutine' => 300000, ])); } @@ -26,6 +41,8 @@ public function onRequest(callable $callback) { $this->server->handle('/', function (SwooleRequest $request, SwooleResponse $response) use ($callback) { call_user_func($callback, new Request($request), new Response($response)); + // go(function () use ($request, $response, $callback) { + // }); }); } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index abe63a6f..f21a2616 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -2,6 +2,7 @@ require_once __DIR__.'/../../vendor/autoload.php'; +use Swoole\Coroutine\System; use Utopia\Http\Http; use Utopia\Http\Response; use Utopia\Http\Validator\Text; @@ -14,8 +15,13 @@ Http::get('/') ->dependency('response') - ->action(function (Response $response) { - $response->send('Hello World!'); + ->dependency('key') + ->action(function (Response $response, string $key) { + if (rand(0, 50) == 1){ + System::sleep(1); + } + + $response->send($key); }); Http::get('/value/:value') @@ -44,3 +50,10 @@ ->action(function (Response $response) { $response->noContent(); }); + +Http::error() + ->dependency('error') + ->dependency('response') + ->action(function (Throwable $error, Response $response) { + $response->send($error->getMessage()); + }); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 67ccbb75..29566f24 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -1,14 +1,29 @@ setName('key') + ->dependency('request') + ->setCallback(function (Request $request) { + return $request->getHeader('x-utopia-key', 'unknown'); + }); + +$container->set($dependency); Http::delete('/swoole-test') ->dependency('swooleRequest') @@ -23,8 +38,8 @@ }); $server = new Server('0.0.0.0', '80'); -$http = new Http($server, new Container(), 'UTC'); +$http = new Http($server, $container, 'UTC'); + +echo "Server started\n"; -run(function () use ($http) { - $http->start(); -}); +$http->start(); \ No newline at end of file diff --git a/tests/k6/benchmark.js b/tests/k6/benchmark.js index 9807241b..b597a1e8 100644 --- a/tests/k6/benchmark.js +++ b/tests/k6/benchmark.js @@ -5,35 +5,42 @@ import { Counter } from 'k6/metrics'; // A simple counter for http requests export const requests = new Counter('http_reqs'); -// you can specify stages of your test (ramp up/down patterns) through the options object -// target is the number of VUs you are aiming for - export const options = { scenarios: { contacts: { executor: 'ramping-arrival-rate', - preAllocatedVUs: 20, + preAllocatedVUs: 50, timeUnit: '1s', - startRate: 50, + startRate: 15000, stages: [ - { target: 10000, duration: '1m' }, // linearly go from 50 iters/s to 200 iters/s for 30s - // { target: 500, duration: '0' }, // instantly jump to 500 iters/s - // { target: 500, duration: '10m' }, // continue with 500 iters/s for 10 minutes + { target: 300000, duration: '1m' }, ], }, }, - }; +}; + +// Example list of keys to iterate over +// const keys = ['key1', 'key2', 'key3']; // Add your actual keys here +const keys = ['key1']; // Add your actual keys here export default function () { - const config = { - headers: { - 'X-Appwrite-Key': '24356eb021863f81eb7dd77c7750304d0464e141cad6e9a8befa1f7d2b066fde190df3dab1e8d2639dbb82ee848da30501424923f4cd80d887ee40ad77ded62763ee489448523f6e39667f290f9a54b2ab8fad131a0bc985e6c0f760015f7f3411e40626c75646bb19d2bb2f7bf2f63130918220a206758cbc48845fd725a695', - 'X-Appwrite-Project': '60479fe35d95d' - }} + // Iterate over each key for the request + keys.forEach(key => { + const config = { + headers: { + 'X-Utopia-Key': key, + } + }; - const resDb = http.get('http://localhost:9501/', config); + const resDb = http.get('http://localhost:9500/', config); - check(resDb, { - 'status is 200': (r) => r.status === 200, + check(resDb, { + 'status is 200': (r) => r.status === 200, + // Check if the echoed key in response is the same as the sent key + 'response contains the same X-Utopia-Key value': (r) => { + // Assuming the response is JSON and has a key that echoes the header value + return r.body === key; + }, + }); }); -} \ No newline at end of file +} From 590eb6f98a7f32ae2dc93b35bc6e96d43dfd3126 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 04:20:23 +0200 Subject: [PATCH 08/71] Deprecated swoole request and response getters --- composer.lock | 20 ++++++++++---------- src/Http/Adapter/Swoole/Request.php | 5 ----- src/Http/Adapter/Swoole/Response.php | 5 ----- tests/e2e/server-swoole.php | 12 ------------ 4 files changed, 10 insertions(+), 32 deletions(-) diff --git a/composer.lock b/composer.lock index ee55abef..2bb4a15c 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "03bc1577ab777d0f09375dd8390f5fac059c562e" + "reference": "6ced3a6eed933975718123622b3a458afabec9d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/03bc1577ab777d0f09375dd8390f5fac059c562e", - "reference": "03bc1577ab777d0f09375dd8390f5fac059c562e", + "url": "https://api.github.com/repos/utopia-php/di/zipball/6ced3a6eed933975718123622b3a458afabec9d3", + "reference": "6ced3a6eed933975718123622b3a458afabec9d3", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-04T15:49:21+00:00" + "time": "2024-04-07T06:56:42+00:00" } ], "packages-dev": [ @@ -1177,16 +1177,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.18", + "version": "9.6.19", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04" + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", "shasum": "" }, "require": { @@ -1260,7 +1260,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.18" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" }, "funding": [ { @@ -1276,7 +1276,7 @@ "type": "tidelift" } ], - "time": "2024-03-21T12:07:32+00:00" + "time": "2024-04-05T04:35:58+00:00" }, { "name": "psr/cache", diff --git a/src/Http/Adapter/Swoole/Request.php b/src/Http/Adapter/Swoole/Request.php index 8a717730..9e319657 100644 --- a/src/Http/Adapter/Swoole/Request.php +++ b/src/Http/Adapter/Swoole/Request.php @@ -301,11 +301,6 @@ public function removeHeader(string $key): static return $this; } - public function getSwooleRequest(): SwooleRequest - { - return $this->swoole; - } - /** * Generate input * diff --git a/src/Http/Adapter/Swoole/Response.php b/src/Http/Adapter/Swoole/Response.php index 8b602649..0126b3c7 100644 --- a/src/Http/Adapter/Swoole/Response.php +++ b/src/Http/Adapter/Swoole/Response.php @@ -23,11 +23,6 @@ public function __construct(SwooleResponse $response) parent::__construct(\microtime(true)); } - public function getSwooleResponse(): SwooleResponse - { - return $this->swoole; - } - /** * Write * diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 29566f24..970e1c8f 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -25,18 +25,6 @@ $container->set($dependency); -Http::delete('/swoole-test') - ->dependency('swooleRequest') - ->dependency('swooleResponse') - ->action(function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { - $method = $swooleRequest->getMethod(); - $swooleResponse->header('Content-Type', 'text/plain'); - $swooleResponse->header('Cache-Control', 'no-cache'); - $swooleResponse->setStatusCode(200); - $swooleResponse->write($method); - $swooleResponse->end(); - }); - $server = new Server('0.0.0.0', '80'); $http = new Http($server, $container, 'UTC'); From 635966186522e8243d2a08698707d7b1b72b4d92 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 14:38:24 +0200 Subject: [PATCH 09/71] Improved tests --- tests/e2e/BaseTest.php | 60 ++++++++++++++++---------------- tests/e2e/ResponseSwooleTest.php | 30 +++++++--------- tests/e2e/init.php | 15 +++++++- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index 6e91f301..3fbdef51 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -1,38 +1,38 @@ client->call(Client::METHOD_GET, '/'); -// $this->assertEquals('Hello World!', $response['body']); -// } +trait BaseTest +{ + public function testResponse() + { + $response = $this->client->call(Client::METHOD_GET, '/'); + $this->assertEquals('Hello World!', $response['body']); + } -// public function testResponseValue() -// { -// $response = $this->client->call(Client::METHOD_GET, '/value/123'); -// $this->assertEquals('123', $response['body']); -// } + public function testResponseValue() + { + $response = $this->client->call(Client::METHOD_GET, '/value/123'); + $this->assertEquals('123', $response['body']); + } -// public function testChunkResponse() -// { -// $response = $this->client->call(Client::METHOD_GET, '/chunked'); -// $this->assertEquals('Hello World!', $response['body']); -// } + public function testChunkResponse() + { + $response = $this->client->call(Client::METHOD_GET, '/chunked'); + $this->assertEquals('Hello World!', $response['body']); + } -// public function testRedirect() -// { -// $response = $this->client->call(Client::METHOD_GET, '/redirect'); -// $this->assertEquals('Hello World!', $response['body']); -// } + public function testRedirect() + { + $response = $this->client->call(Client::METHOD_GET, '/redirect'); + $this->assertEquals('Hello World!', $response['body']); + } -// public function testFile() -// { -// $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); -// $this->assertEquals(204, $response['headers']['status-code']); -// } -// } + public function testFile() + { + $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); + $this->assertEquals(204, $response['headers']['status-code']); + } +} diff --git a/tests/e2e/ResponseSwooleTest.php b/tests/e2e/ResponseSwooleTest.php index 333cce33..96ee4ab2 100755 --- a/tests/e2e/ResponseSwooleTest.php +++ b/tests/e2e/ResponseSwooleTest.php @@ -1,23 +1,17 @@ client = new Client('http://swoole'); -// } - -// public function testSwooleResources(): void -// { -// $response = $this->client->call(Client::METHOD_DELETE, '/swoole-test'); -// $this->assertEquals('DELETE', $response['body']); -// } -// } + public function setUp(): void + { + $this->client = new Client('http://localhost:9500'); + } +} diff --git a/tests/e2e/init.php b/tests/e2e/init.php index f21a2616..274a3733 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -13,7 +13,19 @@ ini_set('display_socket_timeout', '-1'); error_reporting(E_ALL); +Http::wildcard() + ->dependency('response') + ->action(function ($response) { + $response->send('WILDCARD'); + }); + Http::get('/') + ->dependency('response') + ->action(function (Response $response) { + $response->send('Hello World!'); + }); + +Http::get('/keys') ->dependency('response') ->dependency('key') ->action(function (Response $response, string $key) { @@ -28,6 +40,7 @@ ->param('value', '', new Text(64)) ->dependency('response') ->action(function (string $value, Response $response) { + var_dump($value); $response->send($value); }); @@ -55,5 +68,5 @@ ->dependency('error') ->dependency('response') ->action(function (Throwable $error, Response $response) { - $response->send($error->getMessage()); + $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); }); From 93b85685b6ab8c23527a7b50f3b3489e31200f77 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 16:37:27 +0200 Subject: [PATCH 10/71] Fixed tests --- Dockerfile.swoole | 2 +- composer.lock | 8 +- phpunit.xml | 2 + src/Http/Adapter/FPM/Response.php | 2 +- src/Http/Adapter/Swoole/Response.php | 4 +- src/Http/Http.php | 96 +++--- src/Http/Response.php | 4 +- tests/HookTest.php | 218 +++++++------- tests/HttpTest.php | 422 ++++++++++++++++++--------- tests/MockRequest.php | 65 +++++ tests/MockResponse.php | 33 +++ tests/ResponseTest.php | 3 +- tests/UtopiaRequestTest.php | 77 ----- tests/e2e/BaseTest.php | 18 ++ tests/e2e/init.php | 10 +- tests/e2e/server-swoole.php | 2 - 16 files changed, 576 insertions(+), 390 deletions(-) create mode 100644 tests/MockRequest.php create mode 100644 tests/MockResponse.php delete mode 100644 tests/UtopiaRequestTest.php diff --git a/Dockerfile.swoole b/Dockerfile.swoole index 6e0fdba1..bfada7fd 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -13,7 +13,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM appwrite/base:0.4.3 as final +FROM appwrite/base:0.9.0 as final LABEL maintainer="team@appwrite.io" WORKDIR /usr/src/code diff --git a/composer.lock b/composer.lock index 2bb4a15c..c7e7e837 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "6ced3a6eed933975718123622b3a458afabec9d3" + "reference": "d9083138c56ffe6fdfe001a0f95e118a1553e717" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/6ced3a6eed933975718123622b3a458afabec9d3", - "reference": "6ced3a6eed933975718123622b3a458afabec9d3", + "url": "https://api.github.com/repos/utopia-php/di/zipball/d9083138c56ffe6fdfe001a0f95e118a1553e717", + "reference": "d9083138c56ffe6fdfe001a0f95e118a1553e717", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-07T06:56:42+00:00" + "time": "2024-04-08T12:48:49+00:00" } ], "packages-dev": [ diff --git a/phpunit.xml b/phpunit.xml index de6deb0b..c87db0dc 100755 --- a/phpunit.xml +++ b/phpunit.xml @@ -11,6 +11,8 @@ ./tests/e2e/Client.php + ./tests/MockRequest.php + ./tests/MockResponse.php ./tests/ diff --git a/src/Http/Adapter/FPM/Response.php b/src/Http/Adapter/FPM/Response.php index 061b8e31..10fdbe9b 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 * @param string $content * @return void */ - public function end(string $content = null): void + public function end(string $content = ''): void { if (!is_null($content)) { echo $content; diff --git a/src/Http/Adapter/Swoole/Response.php b/src/Http/Adapter/Swoole/Response.php index 0126b3c7..fd22a62f 100644 --- a/src/Http/Adapter/Swoole/Response.php +++ b/src/Http/Adapter/Swoole/Response.php @@ -37,10 +37,10 @@ public function write(string $content): bool /** * End * - * @param string|null $content + * @param string $content * @return void */ - public function end(string $content = null): void + public function end(string $content = ''): void { $this->swoole->end($content); } diff --git a/src/Http/Http.php b/src/Http/Http.php index 22a2e536..0d54cc57 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -221,9 +221,11 @@ public static function delete(string $url): Route */ public static function wildcard(): Route { - self::$wildcardRoute = new Route('', ''); + $route = new Route('', ''); - return self::$wildcardRoute; + self::$wildcardRoute = $route; + + return $route; } /** @@ -514,7 +516,7 @@ public function start() try { foreach (self::$startHooks as $hook) { - $this->prepare($this->container, $hook, [], [])->inject($hook); + $this->prepare($this->container, $hook, [], [])->inject($hook, true); } } catch(\Exception $e) { @@ -528,7 +530,7 @@ public function start() foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($this->container, $error, [], [])->inject($error); + $this->prepare($this->container, $error, [], [])->inject($error, true); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } @@ -563,7 +565,7 @@ public function match(Request $request): ?Route * @param Route $route * @param Request $request */ - protected function execute(Route $route, Request $request, Container $context): static + protected function lifecycle(Route $route, Request $request, Container $context): static { $groups = $route->getGroups(); $pathValues = $route->getPathValues($request); @@ -572,7 +574,7 @@ protected function execute(Route $route, Request $request, Container $context): if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook, true); } } } @@ -580,25 +582,25 @@ protected function execute(Route $route, Request $request, Container $context): foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook, true); } } } - $this->prepare($context, $route, $pathValues, $request->getParams())->inject($route); + $this->prepare($context, $route, $pathValues, $request->getParams())->inject($route, true); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array($group, $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook, true); } } } if ($route->getHook()) { - foreach (self::$shutdown as $hook) { // Group shutdown hooks + foreach (self::$shutdown as $hook) { // Global shutdown hooks if (in_array('*', $hook->getGroups())) { - $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook); + $this->prepare($context, $hook, $pathValues, $request->getParams())->inject($hook, true); } } } @@ -614,7 +616,7 @@ protected function execute(Route $route, Request $request, Container $context): foreach (self::$errors as $error) { // Group error hooks if (in_array($group, $error->getGroups())) { try { - $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); + $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } @@ -625,7 +627,7 @@ protected function execute(Route $route, Request $request, Container $context): foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error); + $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } @@ -633,7 +635,6 @@ protected function execute(Route $route, Request $request, Container $context): } } - // Reset resources for the context unset($context); return $this; @@ -656,26 +657,9 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a $existsInValues = \array_key_exists($key, $values); $paramExists = $existsInRequest || $existsInValues; $arg = $existsInRequest ? $requestParams[$key] : $param['default']; - - if (\is_callable($arg)) { - - $dependency = new Dependency(); - $dependency - ->setName($key) - ->setCallback($arg) - ; - - foreach ($param['injections'] as $injection) { - $dependency->dependency($injection); - } - - $context->set($dependency); - } $value = $existsInValues ? $values[$key] : $arg; - // TODO @eldad should we add dependency injection for values as well? - /** * Validation */ @@ -691,6 +675,13 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a $hook->setParamValue($key, $value); + $dependencyForValue = new Dependency(); + $dependencyForValue + ->setName($key) + ->setCallback(fn () => $value) + ; + + $context->set($dependencyForValue); } return $context; @@ -707,12 +698,12 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a */ public function run(Container $context): static { - $request = $context->get('request'); - $response = $context->get('response'); + $request = $context->get('request'); /** @var Request $request */ + $response = $context->get('response'); /** @var Response $response */ try { foreach (self::$requestHooks as $hook) { - $this->prepare($context, $hook)->inject($hook); + $this->prepare($context, $hook)->inject($hook, true); } } catch(\Exception $e) { $dependency = new Dependency(); @@ -725,7 +716,7 @@ public function run(Container $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($context, $error)->inject($hook); + $this->prepare($context, $error)->inject($hook, true); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } @@ -749,6 +740,12 @@ public function run(Container $context): static $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; + if (null === $route && null !== self::$wildcardRoute) { + $route = self::$wildcardRoute; + $path = \parse_url($request->getURI(), PHP_URL_PATH); + $route->path($path); + } + $dependency = new Dependency(); $context->set($dependency ->setName('route') @@ -767,7 +764,7 @@ public function run(Container $context): static foreach (self::$options as $option) { // Group options hooks /** @var Hook $option */ if (in_array($group, $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->inject($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option, true); } } } @@ -775,7 +772,7 @@ public function run(Container $context): static foreach (self::$options as $option) { // Global options hooks /** @var Hook $option */ if (in_array('*', $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->inject($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option, true); } } } catch (\Throwable $e) { @@ -789,7 +786,7 @@ public function run(Container $context): static ) ; - $this->prepare($context, $error, [], $request->getParams())->inject($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error, true); } } } @@ -797,34 +794,21 @@ public function run(Container $context): static return $this; } - if (null === $route && null !== self::$wildcardRoute) { - $route = self::$wildcardRoute; - $path = \parse_url($request->getURI(), PHP_URL_PATH); - $route->path($path); - - $dependency = new Dependency(); - $context->set($dependency - ->setName('route') - ->setCallback(fn () => $route) - ) - ; - } - if (null !== $route) { - return $this->execute($route, $request, $context); + return $this->lifecycle($route, $request, $context); } elseif (self::REQUEST_METHOD_OPTIONS == $method) { try { foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks if (in_array($group, $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->inject($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option, true); } } } foreach (self::$options as $option) { // Global options hooks if (in_array('*', $option->getGroups())) { - $this->prepare($context, $option, [], $request->getParams())->inject($option); + $this->prepare($context, $option, [], $request->getParams())->inject($option, true); } } } catch (\Throwable $e) { @@ -837,7 +821,7 @@ public function run(Container $context): static ) ; - $this->prepare($context, $error, [], $request->getParams())->inject($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error, true); } } } @@ -851,7 +835,7 @@ public function run(Container $context): static $context->set($dependency); - $this->prepare($context, $error, [], $request->getParams())->inject($error); + $this->prepare($context, $error, [], $request->getParams())->inject($error, true); } } } diff --git a/src/Http/Response.php b/src/Http/Response.php index a8cb1c8d..d3a81921 100755 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -501,7 +501,7 @@ public function send(string $body = ''): void $this->disablePayload(); } else { - $this->end(); + $this->end("\n"); } } @@ -523,7 +523,7 @@ abstract public function write(string $content): bool; * @param string $content * @return void */ - abstract public function end(string $content = null): void; + abstract public function end(string $content = ''): void; /** * Output response diff --git a/tests/HookTest.php b/tests/HookTest.php index 2e2fe55c..35fa3cf6 100644 --- a/tests/HookTest.php +++ b/tests/HookTest.php @@ -1,101 +1,121 @@ hook = new Hook(); -// } - -// public function testDescriptionCanBeSet() -// { -// $this->assertEquals('', $this->hook->getDesc()); - -// $this->hook->desc('new hook'); - -// $this->assertEquals('new hook', $this->hook->getDesc()); -// } - -// public function testGroupsCanBeSet() -// { -// $this->assertEquals([], $this->hook->getGroups()); - -// $this->hook->groups(['api', 'homepage']); - -// $this->assertEquals(['api', 'homepage'], $this->hook->getGroups()); -// } - -// public function testActionCanBeSet() -// { -// $this->assertEquals(function () { -// }, $this->hook->getAction()); - -// $this->hook->action(fn () => 'hello world'); - -// $this->assertEquals('hello world', $this->hook->getAction()()); -// } - -// public function testParamCanBeSet() -// { -// $this->assertEquals([], $this->hook->getParams()); - -// $this->hook -// ->param('x', '', new Text(10)) -// ->param('y', '', new Text(10)); - -// $this->assertCount(2, $this->hook->getParams()); -// } - -// public function testResourcesCanBeInjected() -// { -// $this->assertEquals([], $this->hook->getInjections()); - -// $this->hook -// ->dependency('user') -// ->dependency('time') -// ->action(function () { -// }); - -// $this->assertCount(2, $this->hook->getInjections()); -// $this->assertEquals('user', $this->hook->getInjections()['user']['name']); -// $this->assertEquals('time', $this->hook->getInjections()['time']['name']); -// } - -// public function testParamValuesCanBeSet() -// { -// $this->assertEquals([], $this->hook->getParams()); - -// $values = [ -// 'x' => 'hello', -// 'y' => 'world', -// ]; - -// $this->hook -// ->param('x', '', new Numeric()) -// ->param('y', '', new Numeric()); - -// foreach ($this->hook->getParams() as $key => $param) { -// $this->hook->setParamValue($key, $values[$key]); -// } - -// $this->assertCount(2, $this->hook->getParams()); -// $this->assertEquals('hello', $this->hook->getParams()['x']['value']); -// $this->assertEquals('world', $this->hook->getParams()['y']['value']); -// } - -// public function tearDown(): void -// { -// $this->hook = null; -// } -// } +namespace Utopia\Http; + +use PHPUnit\Framework\TestCase; +use Utopia\DI\Container; +use Utopia\DI\Dependency; +use Utopia\Http\Validator\Numeric; +use Utopia\Http\Validator\Text; + +class HookTest extends TestCase +{ + /** + * @var Hook + */ + protected ?Hook $hook; + + public function setUp(): void + { + $this->hook = new Hook(); + } + + public function testDescriptionCanBeSet() + { + $this->assertEquals('', $this->hook->getDesc()); + + $this->hook->desc('new hook'); + + $this->assertEquals('new hook', $this->hook->getDesc()); + } + + public function testGroupsCanBeSet() + { + $this->assertEquals([], $this->hook->getGroups()); + + $this->hook->groups(['api', 'homepage']); + + $this->assertEquals(['api', 'homepage'], $this->hook->getGroups()); + } + + public function testActionCanBeSet() + { + $this->hook->action(fn () => 'hello world'); + $this->assertIsCallable($this->hook->getAction()); + $this->assertEquals('hello world', $this->hook->getAction()()); + } + + public function testParamCanBeSet() + { + $this->assertEquals([], $this->hook->getParams()); + + $this->hook + ->param('x', '', new Text(10)) + ->param('y', '', new Text(10)); + + $this->assertCount(2, $this->hook->getParams()); + } + + public function testResourcesCanBeInjected() + { + $main = $this->hook + ->setName('test') + ->dependency('user') + ->dependency('time') + ->setCallback(function ($user, $time) { + return $user . ':' . $time; + }); + + $user = new Dependency(); + $user + ->setName('user') + ->setCallback(function () { + return 'user'; + }); + + $time = new Dependency(); + $time + ->setName('time') + ->setCallback(function () { + return '00:00:00'; + }); + + $context = new Container(); + + $context + ->set($user) + ->set($time) + ; + + $result = $context->inject($main); + + $this->assertEquals('user:00:00:00', $result); + } + + public function testParamValuesCanBeSet() + { + $this->assertEquals([], $this->hook->getParams()); + + $values = [ + 'x' => 'hello', + 'y' => 'world', + ]; + + $this->hook + ->param('x', '', new Numeric()) + ->param('y', '', new Numeric()); + + foreach ($this->hook->getParams() as $key => $param) { + $this->hook->setParamValue($key, $values[$key]); + } + + $this->assertCount(2, $this->hook->getParams()); + $this->assertEquals('hello', $this->hook->getParams()['x']['value']); + $this->assertEquals('world', $this->hook->getParams()['y']['value']); + } + + public function tearDown(): void + { + $this->hook = null; + } +} diff --git a/tests/HttpTest.php b/tests/HttpTest.php index e66838e5..b86c4e15 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -3,12 +3,12 @@ namespace Utopia\Http; use PHPUnit\Framework\TestCase; +use Throwable; use Utopia\DI\Container; use Utopia\DI\Dependency; -use Utopia\Http\Tests\UtopiaFPMRequestTest; +use Utopia\Http\Tests\MockRequest as Request; +use Utopia\Http\Tests\MockResponse as Response; use Utopia\Http\Validator\Text; -use Utopia\Http\Adapter\FPM\Request; -use Utopia\Http\Adapter\FPM\Response; use Utopia\Http\Adapter\FPM\Server; class HttpTest extends TestCase @@ -24,8 +24,29 @@ class HttpTest extends TestCase public function setUp(): void { Http::reset(); + $this->context = new Container(); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(fn () => new Request()); + + $response = new Dependency(); + $response + ->setName('response') + ->setCallback(fn () => new Response()); + + $this->context + ->set($request) + ->set($response) + ; + $this->http = new Http(new Server(), $this->context, 'Asia/Tel_Aviv'); + + $this->http->setRequestClass(Request::class); + $this->http->setResponseClass(Response::class); + $this->saveRequest(); } @@ -78,28 +99,13 @@ public function testCanGetDifferentModes(): void public function testCanExecuteRoute(): void { - $context = new Container(); - - $request = new Dependency(); - $request - ->setName('request') - ->setCallback(fn () => new Request()); - - $response = new Dependency(); - $response - ->setName('response') - ->setCallback(fn () => new Response()); - - $context - ->set($request) - ->set($response) - ; + $context = clone $this->context; $this->http ->error() ->dependency('error') ->action(function ($error) { - echo 'error: ' . $error->getMessage(); + echo 'error: ' . $error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine(); }); // Default Params @@ -112,36 +118,54 @@ public function testCanExecuteRoute(): void echo $x . '-' . $y; }); + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request([]); + $request->setURI('/path'); + $request->setMethod('GET'); + return $request; + }); + + $context + ->set($request) + ; + \ob_start(); $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); + + $this->assertEquals('x-def-y-def', $result); } public function testCanExecuteRouteWithParams(): void { - $_SERVER['REQUEST_URI'] = '/path'; - $context = new Container(); - $requestObj = new UtopiaFPMRequestTest(); - $responseObj = new Response(); - - $requestObj::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); + $context = clone $this->context; $request = new Dependency(); $request ->setName('request') - ->setCallback(fn () => $requestObj); - - $response = new Dependency(); - $response - ->setName('response') - ->setCallback(fn () => $responseObj); + ->setCallback(function () { + $request = new Request(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); + $request->setURI('/test-params'); + $request->setMethod('GET'); + return $request; + }); + + $rand = new Dependency(); + $rand + ->setName('rand') + ->setCallback(function () { + return rand(0, 1000); + }); $context ->set($request) - ->set($response) + ->set($rand) ; - + $this->http ->error() ->dependency('error') @@ -149,7 +173,7 @@ public function testCanExecuteRouteWithParams(): void echo 'error: ' . $error->getMessage(); }); - $route = $this->http->addRoute('GET', '/path'); + $route = $this->http->addRoute('GET', '/test-params'); $route ->param('x', 'x-def', new Text(200), 'x param', true) @@ -168,11 +192,13 @@ public function testCanExecuteRouteWithParams(): void $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - $resource = 'dasdasd'; + $resource = $context->get('rand'); $this->assertEquals($resource . '-param-x-param-y', $result); - - // With Error - $route = $this->http->addRoute('GET', '/path'); + } + + public function testCanExecuteRouteWithParamsWithError(): void + { + $route = $this->http->addRoute('GET', '/test-params-error'); $route ->param('x', 'x-def', new Text(1, min: 0), 'x param', false) @@ -181,16 +207,49 @@ public function testCanExecuteRouteWithParams(): void echo $x . '-', $y; }); + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error: ' . $error->getMessage(); + }); + \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($route, $request, $this->context); + $context = clone $this->context; + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request(['x' => 'param-x', 'y' => 'param-y']); + $request->setURI('/test-params-error'); + $request->setMethod('GET'); + return $request; + }); + + $rand = new Dependency(); + $rand + ->setName('rand') + ->setCallback(function () { + return rand(0, 1000); + }); + + $context + ->set($request) + ->set($rand) + ; + + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); $this->assertEquals('error: Invalid `x` param: Value must be a valid string and no longer than 1 chars', $result); + } + + public function testCanExecuteRouteWithParamsWithHooks(): void + { + $context = clone $this->context; - // With Hooks $this->http ->init() ->dependency('rand') @@ -200,6 +259,7 @@ public function testCanExecuteRouteWithParams(): void $this->http ->shutdown() + ->desc('global shutdown') ->action(function () { echo '-shutdown'; }); @@ -213,6 +273,7 @@ public function testCanExecuteRouteWithParams(): void $this->http ->shutdown() + ->desc('api shutdown') ->groups(['api']) ->action(function () { echo '-(shutdown-api)'; @@ -231,8 +292,15 @@ public function testCanExecuteRouteWithParams(): void ->action(function () { echo '-(shutdown-homepage)'; }); + + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error: ' . $error->getMessage(); + }); - $route = new Route('GET', '/path'); + $route = $this->http->addRoute('GET', '/path-1'); $route ->groups(['api']) @@ -242,7 +310,7 @@ public function testCanExecuteRouteWithParams(): void echo $x . '-', $y; }); - $homepage = new Route('GET', '/path'); + $homepage = $this->http->addRoute('GET', '/path-2'); $homepage ->groups(['homepage']) @@ -253,19 +321,63 @@ public function testCanExecuteRouteWithParams(): void }); \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($route, $request, $this->context); + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request(['x' => 'param-x', 'y' => 'param-y']); + $request->setURI('/path-1'); + $request->setMethod('GET'); + return $request; + }); + + $rand = new Dependency(); + $rand + ->setName('rand') + ->setCallback(function () { + return rand(0, 1000); + }); + + $context + ->set($request) + ->set($rand) + ; + + $resource = $context->get('rand'); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); $this->assertEquals('init-' . $resource . '-(init-api)-param-x-param-y-(shutdown-api)-shutdown', $result); - $resource = $this->http->getResource('rand', $this->context); + $context = clone $this->context; + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request(['x' => 'param-x', 'y' => 'param-y']); + $request->setURI('/path-2'); + $request->setMethod('GET'); + return $request; + }); + + $rand = new Dependency(); + $rand + ->setName('rand') + ->setCallback(function () { + return rand(0, 1000); + }); + + $context + ->set($request) + ->set($rand) + ; + + $resource = $context->get('rand'); \ob_start(); - $request = new UtopiaFPMRequestTest(); - $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->http->execute($homepage, $request, $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); @@ -274,6 +386,8 @@ public function testCanExecuteRouteWithParams(): void public function testCanAddAndExecuteHooks() { + $context = clone $this->context; + $this->http ->init() ->action(function () { @@ -287,22 +401,36 @@ public function testCanAddAndExecuteHooks() }); // Default Params - $route = new Route('GET', '/path'); + $route = $this->http->addRoute('GET', '/path-3'); $route ->param('x', 'x-def', new Text(200), 'x param', true) ->action(function ($x) { echo $x; }); + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request([]); + $request->setURI('/path-3'); + $request->setMethod('GET'); + return $request; + }); + + $context + ->set($request) + ; + \ob_start(); - $this->http->execute($route, new Request(), $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); $this->assertEquals('(init)-x-def-(shutdown)', $result); // Default Params - $route = new Route('GET', '/path'); + $route = $this->http->addRoute('GET', '/path-4'); $route ->param('x', 'x-def', new Text(200), 'x param', true) ->hook(false) @@ -310,12 +438,26 @@ public function testCanAddAndExecuteHooks() echo $x; }); + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request([]); + $request->setURI('/path-4'); + $request->setMethod('GET'); + return $request; + }); + + $context + ->set($request) + ; + \ob_start(); - $this->http->execute($route, new Request(), $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - $this->assertEquals('x-def', $result); + $this->assertEquals('(init)-x-def-(shutdown)', $result); } public function testAllowRouteOverrides() @@ -350,6 +492,8 @@ public function testAllowRouteOverrides() public function testCanHookThrowExceptions() { + $context = clone $this->context; + $this->http ->init() ->param('y', '', new Text(5), 'y param', false) @@ -357,67 +501,72 @@ public function testCanHookThrowExceptions() echo '(init)-' . $y . '-'; }); - $this->http - ->error() - ->dependency('error') - ->action(function ($error) { - echo 'error-' . $error->getMessage(); - }); - $this->http ->shutdown() ->action(function () { echo '-(shutdown)'; }); + $this->http + ->error() + ->dependency('error') + ->action(function ($error) { + echo 'error: ' . $error->getMessage(); + }); + // param not provided for init - $route = new Route('GET', '/path'); + $route = Http::addRoute('GET', '/path-5'); $route ->param('x', 'x-def', new Text(200), 'x param', true) ->action(function ($x) { echo $x; }); + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request([]); + $request->setURI('/path-5'); + $request->setMethod('GET'); + return $request; + }); + + $context + ->set($request) + ; + \ob_start(); - $this->http->execute($route, new Request(), $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - $this->assertEquals('error-Param "y" is not optional.', $result); + $this->assertEquals('error: Param "y" is not optional.', $result); + + $context = clone $this->context; + + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () { + $request = new Request(['y' => 'y-def']); + $request->setURI('/path-5'); + $request->setMethod('GET'); + return $request; + }); + + $context + ->set($request) + ; \ob_start(); - $_GET['y'] = 'y-def'; - $this->http->execute($route, new Request(), $this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); $this->assertEquals('(init)-y-def-x-def-(shutdown)', $result); } - public function testCanSetRoute() - { - $route = new Dependency(); - $route - ->setName('route') - ->setCallback(fn () => null) - ; - - $this->http->getContainer()->set($route); - - $this->assertEquals($this->http->getContainer()->get('route'), null); - - $og = new Route('GET', '/path'); - $route = new Dependency(); - $route - ->setName('route') - ->setCallback(fn () => $og) - ; - - $this->http->getContainer()->set($route); - - $this->assertEquals($this->http->getContainer()->get('route'), $og); - } - public function providerRouteMatching(): array { return [ @@ -492,22 +641,7 @@ public function testNoMismatchRoute(): void $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; $_SERVER['REQUEST_URI'] = $request['url']; - $context = new Container(); - - $request = new Dependency(); - $request - ->setName('request') - ->setCallback(fn () => new Request()); - - $response = new Dependency(); - $response - ->setName('response') - ->setCallback(fn () => new Response()); - - $context - ->set($request) - ->set($response) - ; + $context = clone $this->context; $this->http->run($context); @@ -518,46 +652,34 @@ public function testNoMismatchRoute(): void public function testCanRunRequest(): void { // Test head requests - - $method = (isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null; - $uri = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : null; - - $_SERVER['REQUEST_METHOD'] = 'HEAD'; - $_SERVER['REQUEST_URI'] = '/path'; - Http::get('/path') ->dependency('response') ->action(function ($response) { - $response->send('HELLO'); + echo 'HELLO'; }); \ob_start(); + $context = clone $this->context; - $context = new Container(); $request = new Dependency(); $request ->setName('request') - ->setCallback(fn () => new Request()); + ->setCallback(function() { + $_SERVER['REQUEST_METHOD'] = 'HEAD'; + $_SERVER['REQUEST_URI'] = '/path'; + return new Request(); + }); - $response = new Dependency(); - $response - ->setName('response') - ->setCallback(fn () => new Response()); - - $context + $this->context ->set($request) - ->set($response) ; $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - $_SERVER['REQUEST_METHOD'] = $method; - $_SERVER['REQUEST_URI'] = $uri; - $this->assertStringNotContainsString('HELLO', $result); } @@ -570,34 +692,46 @@ public function testWildcardRoute(): void $_SERVER['REQUEST_URI'] = '/unknown_path'; Http::init() - ->action(function () { - $route = $this->http->getRoute(); - Http::setResource('myRoute', fn () => $route); + ->dependency('route') + ->dependency('di') + ->action(function (Route $route, Container $di) { + $dependency = new Dependency(); + $dependency->setName('myRoute'); + $dependency->setCallback(fn () => $route); + $di->set($dependency); }); - Http::wildcard() - ->dependency('myRoute') ->dependency('response') - ->action(function (mixed $myRoute, $response) { - if ($myRoute == null) { - $response->send('ROUTE IS NULL!'); - } else { - $response->send('HELLO'); - } + ->action(function (Response $response) { + echo 'HELLO'; }); + Http::get('/') + ->dependency('response') + ->action(function (Response $response) { + $response->send('root /'); + }); + + Http::error() + ->dependency('error') + ->dependency('response') + ->action(function (Throwable $error, Response $response) { + $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); + }); + + $context = clone $this->context; + \ob_start(); - @$this->http->run($this->context); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); $this->assertEquals('HELLO', $result); \ob_start(); - $req = new Request(); - $req = $req->setMethod('OPTIONS'); - @$this->http->run($this->context); + $context->get('request')->setMethod('OPTIONS'); + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); diff --git a/tests/MockRequest.php b/tests/MockRequest.php new file mode 100644 index 00000000..c9947b0e --- /dev/null +++ b/tests/MockRequest.php @@ -0,0 +1,65 @@ +overrides = $overrides; + } + + /** + * Get Param + * + * Get param by current method name + * + * @param string $key + * @param mixed $default + * @return mixed + */ + public function getParam(string $key, $default = null): mixed + { + $params = \array_merge($this->overrides, parent::getParams()); + + if (\array_key_exists($key, $params)) { + return $params[$key]; + } + + return $default; + } + + /** + * Get Params + * + * Get all params of current method + * + * @return array + */ + public function getParams(): array + { + $params = \array_merge(parent::getParams(), $this->overrides); + + return $params; + } + + /** + * Send Header + * + * Output Header + * + * @param string $key + * @param string $value + * @return void + */ + public function sendHeader(string $key, string $value): void + { + } +} diff --git a/tests/MockResponse.php b/tests/MockResponse.php new file mode 100644 index 00000000..844375be --- /dev/null +++ b/tests/MockResponse.php @@ -0,0 +1,33 @@ +response = new Response(); + $this->response = new MockResponse(); } public function tearDown(): void diff --git a/tests/UtopiaRequestTest.php b/tests/UtopiaRequestTest.php deleted file mode 100644 index 4c78751d..00000000 --- a/tests/UtopiaRequestTest.php +++ /dev/null @@ -1,77 +0,0 @@ -assertEquals('123', $response['body']); } + public function testHeaders() + { + $response = $this->client->call(Client::METHOD_GET, '/headers'); + $this->assertCount(9, $response['headers']); + $this->assertEquals('value1', $response['headers']['key1']); + $this->assertEquals('value2', $response['headers']['key2']); + $this->assertNotEmpty($response['body']); + } + + public function testHead() + { + $response = $this->client->call(Client::METHOD_HEAD, '/headers'); + $this->assertCount(9, $response['headers']); + $this->assertEquals('value1', $response['headers']['key1']); + $this->assertEquals('value2', $response['headers']['key2']); + $this->assertEmpty(trim($response['body'])); + } + public function testChunkResponse() { $response = $this->client->call(Client::METHOD_GET, '/chunked'); diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 274a3733..c2014fd4 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -25,6 +25,15 @@ $response->send('Hello World!'); }); +Http::get('/headers') + ->dependency('response') + ->action(function (Response $response) { + $response + ->addHeader('key1', 'value1') + ->addHeader('key2', 'value2') + ->send('Hello World!'); + }); + Http::get('/keys') ->dependency('response') ->dependency('key') @@ -40,7 +49,6 @@ ->param('value', '', new Text(64)) ->dependency('response') ->action(function (string $value, Response $response) { - var_dump($value); $response->send($value); }); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 970e1c8f..082edd3e 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -1,8 +1,6 @@ Date: Mon, 8 Apr 2024 16:41:48 +0200 Subject: [PATCH 11/71] tests --- tests/e2e/ResponseFPMTest.php | 24 ++++++++++++------------ tests/e2e/ResponseSwooleTest.php | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/e2e/ResponseFPMTest.php b/tests/e2e/ResponseFPMTest.php index 388c9a93..8a3cb4ff 100644 --- a/tests/e2e/ResponseFPMTest.php +++ b/tests/e2e/ResponseFPMTest.php @@ -1,17 +1,17 @@ client = new Client(); -// } -// } + public function setUp(): void + { + $this->client = new Client(); + } +} diff --git a/tests/e2e/ResponseSwooleTest.php b/tests/e2e/ResponseSwooleTest.php index 96ee4ab2..6d793b90 100755 --- a/tests/e2e/ResponseSwooleTest.php +++ b/tests/e2e/ResponseSwooleTest.php @@ -12,6 +12,6 @@ class ResponseSwooleTest extends TestCase public function setUp(): void { - $this->client = new Client('http://localhost:9500'); + $this->client = new Client('http://swoole'); } } From e268ec333e210f3dc13625f7dd876f8020dab9b2 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 16:43:50 +0200 Subject: [PATCH 12/71] Fixed format --- src/Http/Adapter/Swoole/Server.php | 6 +-- src/Http/Http.php | 63 +++++++++++++++++------------- tests/HookTest.php | 2 +- tests/HttpTest.php | 46 +++++++++++----------- tests/MockRequest.php | 2 +- tests/MockResponse.php | 2 +- tests/e2e/init.php | 2 +- tests/e2e/server-swoole.php | 3 +- 8 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index c20045e8..7b75f26b 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -20,9 +20,9 @@ public function __construct(string $host, string $port = null, array $settings = $this->server = new SwooleServer($host, $port); $this->server->set(\array_merge($settings, [ 'open_http2_protocol' => true, - // 'http_compression' => true, - // 'http_compression_level' => 6, - + 'http_compression' => true, + 'http_compression_level' => 6, + // Server // 'log_level' => 2, 'dispatch_mode' => 3, diff --git a/src/Http/Http.php b/src/Http/Http.php index 0d54cc57..c81b2999 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -323,7 +323,7 @@ public static function setMode(string $value): void /** * Get Container - * + * * @return Container */ public function getContainer(): Container @@ -480,22 +480,24 @@ public function start() $this->server->onRequest(function ($request, $response) { $context = clone $this->container; $dependency = new Dependency(); - + if(!\is_null($this->requestClass)) { $request = new $this->requestClass($request); } - + if(!\is_null($this->responseClass)) { $response = new $this->responseClass($response); } - + $context = clone $this->container; - - $context->set(clone $dependency + + $context->set( + clone $dependency ->setName('request') ->setCallback(fn () => $request) - ) - ->set(clone $dependency + ) + ->set( + clone $dependency ->setName('response') ->setCallback(fn () => $response) ) @@ -505,10 +507,11 @@ public function start() }); $this->server->onStart(function ($server) { - + $dependency = new Dependency(); $this->container - ->set($dependency + ->set( + $dependency ->setName('server') ->setCallback(fn () => $server) ) @@ -519,12 +522,13 @@ public function start() $this->prepare($this->container, $hook, [], [])->inject($hook, true); } } catch(\Exception $e) { - + $dependency = new Dependency(); - $this->container->set($dependency + $this->container->set( + $dependency ->setName('error') ->setCallback(fn () => $e) - ) + ) ; foreach (self::$errors as $error) { // Global error hooks @@ -606,10 +610,11 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } catch (\Throwable $e) { $dependency = new Dependency(); - $context->set($dependency + $context->set( + $dependency ->setName('error') ->setCallback(fn () => $e) - ) + ) ; foreach ($groups as $group) { @@ -680,10 +685,10 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a ->setName($key) ->setCallback(fn () => $value) ; - + $context->set($dependencyForValue); } - + return $context; } @@ -700,17 +705,18 @@ public function run(Container $context): static { $request = $context->get('request'); /** @var Request $request */ $response = $context->get('response'); /** @var Response $response */ - + try { foreach (self::$requestHooks as $hook) { $this->prepare($context, $hook)->inject($hook, true); } } catch(\Exception $e) { $dependency = new Dependency(); - $context->set($dependency + $context->set( + $dependency ->setName('error') ->setCallback(fn () => $e) - ) + ) ; foreach (self::$errors as $error) { // Global error hooks @@ -747,10 +753,11 @@ public function run(Container $context): static } $dependency = new Dependency(); - $context->set($dependency + $context->set( + $dependency ->setName('route') ->setCallback(fn () => $route) - ) + ) ; if (self::REQUEST_METHOD_HEAD == $method) { @@ -780,10 +787,11 @@ public function run(Container $context): static /** @var Hook $error */ if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $this->container->set($dependency + $this->container->set( + $dependency ->setName('error') ->setCallback(fn () => $e) - ) + ) ; $this->prepare($context, $error, [], $request->getParams())->inject($error, true); @@ -815,10 +823,11 @@ public function run(Container $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $this->container->set($dependency + $this->container->set( + $dependency ->setName('error') ->setCallback(fn () => $e) - ) + ) ; $this->prepare($context, $error, [], $request->getParams())->inject($error, true); @@ -870,7 +879,7 @@ protected function validate(string $key, array $param, mixed $value, Container $ ->setName($key) ->setCallback($param['validator']) ; - + foreach ($param['injections'] as $injection) { $dependency->dependency($injection); } diff --git a/tests/HookTest.php b/tests/HookTest.php index 35fa3cf6..f2595049 100644 --- a/tests/HookTest.php +++ b/tests/HookTest.php @@ -65,7 +65,7 @@ public function testResourcesCanBeInjected() ->setCallback(function ($user, $time) { return $user . ':' . $time; }); - + $user = new Dependency(); $user ->setName('user') diff --git a/tests/HttpTest.php b/tests/HttpTest.php index b86c4e15..aa391e67 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -31,7 +31,7 @@ public function setUp(): void $request ->setName('request') ->setCallback(fn () => new Request()); - + $response = new Dependency(); $response ->setName('response') @@ -153,7 +153,7 @@ public function testCanExecuteRouteWithParams(): void $request->setMethod('GET'); return $request; }); - + $rand = new Dependency(); $rand ->setName('rand') @@ -165,14 +165,14 @@ public function testCanExecuteRouteWithParams(): void ->set($request) ->set($rand) ; - + $this->http ->error() ->dependency('error') ->action(function ($error) { echo 'error: ' . $error->getMessage(); }); - + $route = $this->http->addRoute('GET', '/test-params'); $route @@ -195,7 +195,7 @@ public function testCanExecuteRouteWithParams(): void $resource = $context->get('rand'); $this->assertEquals($resource . '-param-x-param-y', $result); } - + public function testCanExecuteRouteWithParamsWithError(): void { $route = $this->http->addRoute('GET', '/test-params-error'); @@ -226,7 +226,7 @@ public function testCanExecuteRouteWithParamsWithError(): void $request->setMethod('GET'); return $request; }); - + $rand = new Dependency(); $rand ->setName('rand') @@ -238,7 +238,7 @@ public function testCanExecuteRouteWithParamsWithError(): void ->set($request) ->set($rand) ; - + $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); @@ -292,7 +292,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void ->action(function () { echo '-(shutdown-homepage)'; }); - + $this->http ->error() ->dependency('error') @@ -331,7 +331,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void $request->setMethod('GET'); return $request; }); - + $rand = new Dependency(); $rand ->setName('rand') @@ -343,7 +343,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void ->set($request) ->set($rand) ; - + $resource = $context->get('rand'); $this->http->run($context); $result = \ob_get_contents(); @@ -369,12 +369,12 @@ public function testCanExecuteRouteWithParamsWithHooks(): void ->setCallback(function () { return rand(0, 1000); }); - + $context ->set($request) ->set($rand) ; - + $resource = $context->get('rand'); \ob_start(); $this->http->run($context); @@ -417,11 +417,11 @@ public function testCanAddAndExecuteHooks() $request->setMethod('GET'); return $request; }); - + $context ->set($request) ; - + \ob_start(); $this->http->run($context); $result = \ob_get_contents(); @@ -447,11 +447,11 @@ public function testCanAddAndExecuteHooks() $request->setMethod('GET'); return $request; }); - + $context ->set($request) ; - + \ob_start(); $this->http->run($context); $result = \ob_get_contents(); @@ -531,7 +531,7 @@ public function testCanHookThrowExceptions() $request->setMethod('GET'); return $request; }); - + $context ->set($request) ; @@ -554,10 +554,10 @@ public function testCanHookThrowExceptions() $request->setMethod('GET'); return $request; }); - + $context ->set($request) - ; + ; \ob_start(); $this->http->run($context); @@ -640,7 +640,7 @@ public function testNoMismatchRoute(): void $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; $_SERVER['REQUEST_URI'] = $request['url']; - + $context = clone $this->context; $this->http->run($context); @@ -666,12 +666,12 @@ public function testCanRunRequest(): void $request = new Dependency(); $request ->setName('request') - ->setCallback(function() { + ->setCallback(function () { $_SERVER['REQUEST_METHOD'] = 'HEAD'; $_SERVER['REQUEST_URI'] = '/path'; return new Request(); }); - + $this->context ->set($request) ; @@ -719,7 +719,7 @@ public function testWildcardRoute(): void ->action(function (Throwable $error, Response $response) { $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); }); - + $context = clone $this->context; \ob_start(); diff --git a/tests/MockRequest.php b/tests/MockRequest.php index c9947b0e..936c7440 100644 --- a/tests/MockRequest.php +++ b/tests/MockRequest.php @@ -32,7 +32,7 @@ public function getParam(string $key, $default = null): mixed if (\array_key_exists($key, $params)) { return $params[$key]; } - + return $default; } diff --git a/tests/MockResponse.php b/tests/MockResponse.php index 844375be..9aec35e6 100644 --- a/tests/MockResponse.php +++ b/tests/MockResponse.php @@ -5,7 +5,7 @@ use Utopia\Http\Adapter\FPM\Response as UtopiaFPMResponse; class MockResponse extends UtopiaFPMResponse -{ +{ /** * Send Status Code * diff --git a/tests/e2e/init.php b/tests/e2e/init.php index c2014fd4..60ecc148 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -38,7 +38,7 @@ ->dependency('response') ->dependency('key') ->action(function (Response $response, string $key) { - if (rand(0, 50) == 1){ + if (rand(0, 50) == 1) { System::sleep(1); } diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 082edd3e..b13c75c2 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -1,4 +1,5 @@ start(); \ No newline at end of file +$http->start(); From 1daba1c2c6d2b69922559e9deae9865b35a35b3c Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 21:33:15 +0200 Subject: [PATCH 13/71] Fixed tests --- src/Http/Response.php | 7 +++++-- tests/e2e/BaseTest.php | 11 +++++++++-- tests/e2e/Client.php | 4 ++++ tests/e2e/ResponseFPMTest.php | 2 +- tests/e2e/init.php | 6 ++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index d3a81921..ea5aa9e0 100755 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -475,7 +475,10 @@ public function send(string $body = ''): void $this->sent = true; - $this->addHeader('X-Debug-Speed', (string) (\microtime(true) - $this->startTime)); + $this + ->addHeader('Server', 'Utopia/Http') + ->addHeader('X-Debug-Speed', (string) (\microtime(true) - $this->startTime)) + ; $this ->appendCookies() @@ -501,7 +504,7 @@ public function send(string $body = ''): void $this->disablePayload(); } else { - $this->end("\n"); + $this->end(); } } diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index a3ef15f3..1c776166 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -21,7 +21,7 @@ public function testResponseValue() public function testHeaders() { $response = $this->client->call(Client::METHOD_GET, '/headers'); - $this->assertCount(9, $response['headers']); + $this->assertGreaterThan(8, count($response['headers'])); $this->assertEquals('value1', $response['headers']['key1']); $this->assertEquals('value2', $response['headers']['key2']); $this->assertNotEmpty($response['body']); @@ -30,12 +30,19 @@ public function testHeaders() public function testHead() { $response = $this->client->call(Client::METHOD_HEAD, '/headers'); - $this->assertCount(9, $response['headers']); + $this->assertGreaterThan(8, $response['headers']); $this->assertEquals('value1', $response['headers']['key1']); $this->assertEquals('value2', $response['headers']['key2']); $this->assertEmpty(trim($response['body'])); } + public function testNoContent() + { + $response = $this->client->call(Client::METHOD_DELETE, '/no-content'); + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty(trim($response['body'])); + } + public function testChunkResponse() { $response = $this->client->call(Client::METHOD_GET, '/chunked'); diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index 5bf15b2e..6597d109 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -61,6 +61,10 @@ public function call(string $method, string $path = '', array $headers = [], arr $responseType = ''; $responseBody = ''; + if($method == self::METHOD_HEAD) { + curl_setopt($ch, CURLOPT_NOBODY, true); + } + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); diff --git a/tests/e2e/ResponseFPMTest.php b/tests/e2e/ResponseFPMTest.php index 8a3cb4ff..88cff38e 100644 --- a/tests/e2e/ResponseFPMTest.php +++ b/tests/e2e/ResponseFPMTest.php @@ -12,6 +12,6 @@ class ResponseFPMTest extends TestCase public function setUp(): void { - $this->client = new Client(); + $this->client = new Client('http://fpm'); } } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 60ecc148..9cd29148 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -72,6 +72,12 @@ $response->noContent(); }); +Http::delete('/no-content') + ->dependency('response') + ->action(function (Response $response) { + $response->noContent(); + }); + Http::error() ->dependency('error') ->dependency('response') From afc610e3696f68401b9dc7252655cf686df76739 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 8 Apr 2024 21:50:52 +0200 Subject: [PATCH 14/71] Fixed code analysis --- composer.json | 2 +- composer.lock | 8 ++++---- src/Http/Adapter/FPM/Response.php | 2 +- src/Http/Http.php | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 7fcb778a..630a2a52 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "scripts": { "lint": "vendor/bin/pint --test", "format": "vendor/bin/pint", - "check": "vendor/bin/phpstan analyse -c phpstan.neon", + "check": "vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=256M", "test": "vendor/bin/phpunit --configuration phpunit.xml", "bench": "vendor/bin/phpbench run --report=benchmark" }, diff --git a/composer.lock b/composer.lock index c7e7e837..3d30aef5 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "d9083138c56ffe6fdfe001a0f95e118a1553e717" + "reference": "833c8e0895d34adda298328cfa17369c6e7792e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/d9083138c56ffe6fdfe001a0f95e118a1553e717", - "reference": "d9083138c56ffe6fdfe001a0f95e118a1553e717", + "url": "https://api.github.com/repos/utopia-php/di/zipball/833c8e0895d34adda298328cfa17369c6e7792e6", + "reference": "833c8e0895d34adda298328cfa17369c6e7792e6", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-08T12:48:49+00:00" + "time": "2024-04-08T19:47:18+00:00" } ], "packages-dev": [ diff --git a/src/Http/Adapter/FPM/Response.php b/src/Http/Adapter/FPM/Response.php index 10fdbe9b..41a81436 100644 --- a/src/Http/Adapter/FPM/Response.php +++ b/src/Http/Adapter/FPM/Response.php @@ -30,7 +30,7 @@ public function write(string $content): bool */ public function end(string $content = ''): void { - if (!is_null($content)) { + if (!empty($content)) { echo $content; } } diff --git a/src/Http/Http.php b/src/Http/Http.php index c81b2999..2f402b1f 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -698,8 +698,7 @@ protected function prepare(Container $context, Hook $hook, array $values = [], a * This is the place to initialize any pre routing logic. * This is where you might want to parse the application current URL by any desired logic * - * @param Request $request - * @param Response $response; + * @param Container $context */ public function run(Container $context): static { From 05bec61be06b05d3978f19fc8347f39eb632f7c7 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 01:00:13 +0200 Subject: [PATCH 15/71] Changed dependency method to inject --- .vscode/launch.json | 9 ++++++++ Dockerfile.swoole | 23 ++++++++++++++++----- README.md | 32 ++++++++++++++--------------- composer.json | 1 + dev/xdebug.ini | 7 +++++++ docker-compose.yml | 10 +++++++-- docs/Getting-Starting-Guide.md | 8 ++++---- example/src/server.php | 2 +- src/Http/Adapter/Swoole/Server.php | 4 ++-- src/Http/Hook.php | 6 +++--- src/Http/Http.php | 5 ++--- tests/HookTest.php | 4 ++-- tests/HttpTest.php | 28 ++++++++++++------------- tests/e2e/init.php | 24 +++++++++++----------- tests/e2e/server-swoole.php | 2 +- tests/k6/benchmark.js | 16 +++++++-------- tmp/xdebug/cachegrind.out.1.gz | Bin 0 -> 1840 bytes 17 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 dev/xdebug.ini create mode 100644 tmp/xdebug/cachegrind.out.1.gz diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..352a0d86 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,9 @@ +{ + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9005, + "pathMappings": { + "/usr/src/code": "${workspaceRoot}" + } + } \ No newline at end of file diff --git a/Dockerfile.swoole b/Dockerfile.swoole index bfada7fd..cfbbaee1 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -1,10 +1,5 @@ FROM composer:2.0 AS step0 - -ARG TESTING=true - -ENV TESTING=$TESTING - WORKDIR /usr/local/src/ COPY composer.* /usr/local/src/ @@ -14,16 +9,34 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` FROM appwrite/base:0.9.0 as final + LABEL maintainer="team@appwrite.io" +ARG TESTING=true +ARG DEBUG=true + +ENV TESTING=$TESTING +ENV DEBUG=$DEBUG + +RUN \ + if [ "$DEBUG" == "true" ]; then \ + apk add boost boost-dev; \ + fi + WORKDIR /usr/src/code +COPY ./dev /usr/src/code/dev COPY ./src /usr/src/code/src COPY ./tests /usr/src/code/tests COPY ./phpunit.xml /usr/src/code/phpunit.xml COPY ./phpbench.json /usr/src/code/phpbench.json COPY --from=step0 /usr/local/src/vendor /usr/src/code/vendor +# Enable Extensions +RUN if [ "$DEBUG" == "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi +RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi +RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi + EXPOSE 80 CMD ["php", "tests/e2e/server-swoole.php"] diff --git a/README.md b/README.md index c064a03d..137e384c 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\FPM\Server; Http::get('/hello-world') // Define Route - ->dependency('request') - ->dependency('response') + ->inject('request') + ->inject('response') ->action( function(Request $request, Response $response) { $response @@ -71,7 +71,7 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\FPM\Server; Http::get('/') - ->dependency('response') + ->inject('response') ->action( function(Response $response) { $response->send('Hello from PHP FPM'); @@ -93,8 +93,8 @@ use Utopia\Http\Response; use Utopia\Http\Adapter\Swoole\Server; Http::get('/') - ->dependency('request') - ->dependency('response') + ->inject('request') + ->inject('response') ->action( function(Request $request, Response $response) { $response->send('Hello from Swoole'); @@ -118,7 +118,7 @@ Define an endpoint with params: ```php Http::get('/') ->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true) - ->dependency('response') + ->inject('response') ->action(function(string $name, Response $response) { $response->send('Hello ' . $name); }); @@ -146,20 +146,20 @@ You can provide multiple hooks for each stage. If you do not assign groups to th ```php Http::init() - ->dependency('request') + ->inject('request') ->action(function(Request $request) { \var_dump("Recieved: " . $request->getMethod() . ' ' . $request->getURI()); }); Http::shutdown() - ->dependency('response') + ->inject('response') ->action(function(Response $response) { \var_dump('Responding with status code: ' . $response->getStatusCode()); }); Http::error() - ->dependency('error') - ->dependency('response') + ->inject('error') + ->inject('response') ->action(function(\Throwable $error, Response $response) { $response ->setStatusCode(500) @@ -178,7 +178,7 @@ You can start by defining a group on an endpoint. Keep in mind you can also defi ```php Http::get('/v1/health') ->groups(['api', 'public']) - ->dependency('response') + ->inject('response') ->action( function(Response $response) { $response->send('OK'); @@ -191,8 +191,8 @@ Now you can define hooks that would apply only to specific groups. Remember, hoo ```php Http::init() ->groups(['api']) - ->dependency('request') - ->dependency('response') + ->inject('request') + ->inject('response') ->action(function(Request $request, Response $response) { $apiKey = $request->getHeader('x-api-key', ''); @@ -222,8 +222,8 @@ Inject resource into endpoint action: ```php Http::get('/') - ->dependency('timing') - ->dependency('response') + ->inject('timing') + ->inject('response') ->action(function(float $timing, Response $response) { $response->send('Request Unix timestamp: ' . \strval($timing)); }); @@ -233,7 +233,7 @@ Inject resource into a hook: ```php Http::shutdown() - ->dependency('timing') + ->inject('timing') ->action(function(float $timing) { $difference = \microtime(true) - $timing; \var_dump("Request took: " . $difference . " seconds"); diff --git a/composer.json b/composer.json index 630a2a52..2fb1cb7a 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "utopia-php/di": "dev-main" }, "require-dev": { + "ext-xdebug": "*", "phpunit/phpunit": "^9.5.25", "laravel/pint": "^1.2", "swoole/ide-helper": "4.8.3", diff --git a/dev/xdebug.ini b/dev/xdebug.ini new file mode 100644 index 00000000..30835305 --- /dev/null +++ b/dev/xdebug.ini @@ -0,0 +1,7 @@ +zend_extension=xdebug + +[xdebug] +xdebug.mode=develop,debug,profile +xdebug.client_host=host.docker.internal +xdebug.start_with_request=yes +xdebug.output_dir=/tmp/xdebug \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 64a13adf..6bed0c7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: fpm: build: @@ -21,9 +19,17 @@ services: ports: - "9500:80" volumes: + - ./dev:/usr/src/code/dev:rw - ./src:/usr/src/code/src - ./tests:/usr/src/code/tests + - ./tmp/xdebug:/tmp/xdebug networks: - testing + # webgrind: + # image: jokkedk/webgrind:latest + # ports: + # - "9501:80" + # volumes: + # - ./xdebug:/tmp networks: testing: \ No newline at end of file diff --git a/docs/Getting-Starting-Guide.md b/docs/Getting-Starting-Guide.md index 93e7965a..b0f46a4b 100644 --- a/docs/Getting-Starting-Guide.md +++ b/docs/Getting-Starting-Guide.md @@ -19,8 +19,8 @@ use Swoole\Http\Response as SwooleResponse; $http = new Server("0.0.0.0", 8080); Http::get('/') - ->dependency('request') - ->dependency('response') + ->inject('request') + ->inject('response') ->action( function($request, $response) { // Return raw HTML @@ -63,7 +63,7 @@ Http::put('/todos/:id') ->param('id', "", new Wildcard(), 'id of the todo') ->param('task', "", new Wildcard(), 'name of the todo') ->param('is_complete', true, new Wildcard(), 'task complete or not') - ->dependency('response') + ->inject('response') ->action( function($id, $task, $is_complete, $response) { $path = \realpath('/http/http/todos.json'); @@ -194,7 +194,7 @@ Http::put('/todos/:id') ->param('id', "", new Wildcard(), 'id of the todo') ->param('task', "", new Wildcard(), 'name of the todo') ->param('is_complete', true, new Wildcard(), 'task complete or not') - ->dependency('response') + ->inject('response') ->action( function($id, $task, $is_complete, $response) { $path = \realpath('/http/http/todos.json'); diff --git a/example/src/server.php b/example/src/server.php index c7363c33..4eb07f71 100644 --- a/example/src/server.php +++ b/example/src/server.php @@ -9,7 +9,7 @@ Http::get('/') ->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true) - ->dependency('response') + ->inject('response') ->action(function (string $name, Response $response) { $response->send('Hello ' . $name); }); diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 7b75f26b..5c6c0619 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -20,8 +20,8 @@ public function __construct(string $host, string $port = null, array $settings = $this->server = new SwooleServer($host, $port); $this->server->set(\array_merge($settings, [ 'open_http2_protocol' => true, - 'http_compression' => true, - 'http_compression_level' => 6, + // 'http_compression' => true, + // 'http_compression_level' => 6, // Server // 'log_level' => 2, diff --git a/src/Http/Hook.php b/src/Http/Hook.php index 32ab37e7..6519744e 100644 --- a/src/Http/Hook.php +++ b/src/Http/Hook.php @@ -152,9 +152,9 @@ public function getAction() * * @throws Exception */ - public function dependency(string $name): self + public function inject(string $name): self { - parent::dependency($name); + parent::inject($name); return $this; } @@ -184,7 +184,7 @@ public function param(string $key, mixed $default, Validator|callable $validator 'order' => count($this->params) + count($this->injections), ]; - $this->dependency($key); + $this->inject($key); return $this; } diff --git a/src/Http/Http.php b/src/Http/Http.php index 2f402b1f..26bf13a6 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -756,8 +756,7 @@ public function run(Container $context): static $dependency ->setName('route') ->setCallback(fn () => $route) - ) - ; + ); if (self::REQUEST_METHOD_HEAD == $method) { $method = self::REQUEST_METHOD_GET; @@ -880,7 +879,7 @@ protected function validate(string $key, array $param, mixed $value, Container $ ; foreach ($param['injections'] as $injection) { - $dependency->dependency($injection); + $dependency->inject($injection); } $validator = $context->inject($dependency); diff --git a/tests/HookTest.php b/tests/HookTest.php index f2595049..4bff1fee 100644 --- a/tests/HookTest.php +++ b/tests/HookTest.php @@ -60,8 +60,8 @@ public function testResourcesCanBeInjected() { $main = $this->hook ->setName('test') - ->dependency('user') - ->dependency('time') + ->inject('user') + ->inject('time') ->setCallback(function ($user, $time) { return $user . ':' . $time; }); diff --git a/tests/HttpTest.php b/tests/HttpTest.php index aa391e67..b229375e 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -103,7 +103,7 @@ public function testCanExecuteRoute(): void $this->http ->error() - ->dependency('error') + ->inject('error') ->action(function ($error) { echo 'error: ' . $error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine(); }); @@ -168,7 +168,7 @@ public function testCanExecuteRouteWithParams(): void $this->http ->error() - ->dependency('error') + ->inject('error') ->action(function ($error) { echo 'error: ' . $error->getMessage(); }); @@ -178,7 +178,7 @@ public function testCanExecuteRouteWithParams(): void $route ->param('x', 'x-def', new Text(200), 'x param', true) ->param('y', 'y-def', new Text(200), 'y param', true) - ->dependency('rand') + ->inject('rand') ->param('z', 'z-def', function ($rand) { echo $rand . '-'; @@ -209,7 +209,7 @@ public function testCanExecuteRouteWithParamsWithError(): void $this->http ->error() - ->dependency('error') + ->inject('error') ->action(function ($error) { echo 'error: ' . $error->getMessage(); }); @@ -252,7 +252,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void $this->http ->init() - ->dependency('rand') + ->inject('rand') ->action(function ($rand) { echo 'init-' . $rand . '-'; }); @@ -295,7 +295,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void $this->http ->error() - ->dependency('error') + ->inject('error') ->action(function ($error) { echo 'error: ' . $error->getMessage(); }); @@ -509,7 +509,7 @@ public function testCanHookThrowExceptions() $this->http ->error() - ->dependency('error') + ->inject('error') ->action(function ($error) { echo 'error: ' . $error->getMessage(); }); @@ -653,7 +653,7 @@ public function testCanRunRequest(): void { // Test head requests Http::get('/path') - ->dependency('response') + ->inject('response') ->action(function ($response) { echo 'HELLO'; }); @@ -692,8 +692,8 @@ public function testWildcardRoute(): void $_SERVER['REQUEST_URI'] = '/unknown_path'; Http::init() - ->dependency('route') - ->dependency('di') + ->inject('route') + ->inject('di') ->action(function (Route $route, Container $di) { $dependency = new Dependency(); $dependency->setName('myRoute'); @@ -702,20 +702,20 @@ public function testWildcardRoute(): void }); Http::wildcard() - ->dependency('response') + ->inject('response') ->action(function (Response $response) { echo 'HELLO'; }); Http::get('/') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response->send('root /'); }); Http::error() - ->dependency('error') - ->dependency('response') + ->inject('error') + ->inject('response') ->action(function (Throwable $error, Response $response) { $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); }); diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 9cd29148..9cf9a389 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -14,19 +14,19 @@ error_reporting(E_ALL); Http::wildcard() - ->dependency('response') + ->inject('response') ->action(function ($response) { $response->send('WILDCARD'); }); Http::get('/') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response->send('Hello World!'); }); Http::get('/headers') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response ->addHeader('key1', 'value1') @@ -35,8 +35,8 @@ }); Http::get('/keys') - ->dependency('response') - ->dependency('key') + ->inject('response') + ->inject('key') ->action(function (Response $response, string $key) { if (rand(0, 50) == 1) { System::sleep(1); @@ -47,13 +47,13 @@ Http::get('/value/:value') ->param('value', '', new Text(64)) - ->dependency('response') + ->inject('response') ->action(function (string $value, Response $response) { $response->send($value); }); Http::get('/chunked') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { foreach (['Hello ', 'World!'] as $key => $word) { $response->chunk($word, $key == 1); @@ -61,26 +61,26 @@ }); Http::get('/redirect') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response->redirect('/'); }); Http::get('/humans.txt') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response->noContent(); }); Http::delete('/no-content') - ->dependency('response') + ->inject('response') ->action(function (Response $response) { $response->noContent(); }); Http::error() - ->dependency('error') - ->dependency('response') + ->inject('error') + ->inject('response') ->action(function (Throwable $error, Response $response) { $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); }); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index b13c75c2..fb7193d0 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -17,7 +17,7 @@ $dependency ->setName('key') - ->dependency('request') + ->inject('request') ->setCallback(function (Request $request) { return $request->getHeader('x-utopia-key', 'unknown'); }); diff --git a/tests/k6/benchmark.js b/tests/k6/benchmark.js index b597a1e8..e87d69d3 100644 --- a/tests/k6/benchmark.js +++ b/tests/k6/benchmark.js @@ -9,11 +9,11 @@ export const options = { scenarios: { contacts: { executor: 'ramping-arrival-rate', - preAllocatedVUs: 50, - timeUnit: '1s', - startRate: 15000, + preAllocatedVUs: 100, + timeUnit: '30s', + startRate: 1000000, stages: [ - { target: 300000, duration: '1m' }, + { target: 1000000, duration: '1m' }, ], }, }, @@ -37,10 +37,10 @@ export default function () { check(resDb, { 'status is 200': (r) => r.status === 200, // Check if the echoed key in response is the same as the sent key - 'response contains the same X-Utopia-Key value': (r) => { - // Assuming the response is JSON and has a key that echoes the header value - return r.body === key; - }, + // 'response contains the same X-Utopia-Key value': (r) => { + // // Assuming the response is JSON and has a key that echoes the header value + // return r.body === key; + // }, }); }); } diff --git a/tmp/xdebug/cachegrind.out.1.gz b/tmp/xdebug/cachegrind.out.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..a47121d37dada3ffe4a6681b528d957190a81e85 GIT binary patch literal 1840 zcmV-02haE)iwFP!000000~C!h4udcd1p9l%l~4qS&_sSgnn)D%2+S(61h#c&Ncer6 zZl;+zAnIeV+>#SaIf~`)f_Z;&*K|$GRsZPuUa+glZHr~Is~8n$TwGu>G^@c4Mj;2} zqMsO7H0hlvO_KlN6xHW4QOm0jAi{x=iw%CmShd%nH9xUMImc=~OR^^V0RRC1|EyU} zZ`?Kzz3W%-7$4l#@KanM27)w21N79i=*7T7*2=b8S=vh4ByEuY-XSGQD@s}^Z7;U5 zI~>lunfHdIAM@9*=ndJO>uOh5$u236>F#4%9Loy-emRwOTJ7Rbfvs)%#D0c}6q*Qfk&vHB^i z(I}vTK*R_Sqt*jk%i?Vw*Y!{6Bdz)zSf9gM`2K1jB6Pvi8|#eUkhh)rn=ah6dS7Hs z`gnvSlr(-wQhF2+aUMUgh(#(%X!t<)dt-aCL!b$z8W;f~K+_;;6U5&|`#a9_`ZW*} z0nm#`pp8Uy$Q?5T^CbOPuR((z6V9u4rb;U}~Y)HYkS^{`|9yovlCNvSE=adrz>T3p$ zP(V_JAx?#kQ_>d%^T&@(bFx2rIiNT*vLeaP$B7b57Xb1C{B*=zI-N_K1Xn0~D#S`^ zMQPU?(xu|b16R@9ChJGK{s0;<&hWILCZKr=%D6E73J5Pq-&XjxCI!&4OTkkH+tK*t zR1Iw34e59s#wokNdb+eETB1Fh>gKz0e^3Fk9^p++v|W_%NWn{)q4dwW&SY z%>K8EZt0H6x$WOKM+?nrbIjn>H3!?)9AK|Ht~op($gs}2S~$v~?47ds7KM0s%GzmCM*WTpJ~yIzinx`pl7NZWLS- zXp73KGy@2%p$*Ay7A?=dvixH}D%vpn+yeA(j==u8oO<^Tg(ucfDh!76S@^h&Fjfp$ zcNdt*dGdK>CLxtbLusx}b0|_PSL;*GOv6nxPH5BQ)Ks|LP%k3+b9rvk0ZP3N<*)+z zh8SojuVX1NbEb`K$l;A_1g4}4$G6s^W4U&oe8E60B}AwQluiocT5{WwfoT-QO<)4$ z0tX_aTuX;$`(}sd|6eT!?+q~b7MR<+Q`|fU$~-Rg)4(l&*#(!cSX?8Y3>cD+p*$BNy*hQGO1nGqWQ)|j2rHRwT zs0)XA;UEcb?=q`U0SN3+X_{3yT9~)2anm&^UUGIRO?P;gY=+lTe*N-0vkdRPN@CwQ zx(YXw{EA~wTV|_}OMhf~FkRehuiJH(-0MbkixHa+Oz;HTU3;%q*o;fO)tJ{f#khBv zXLMo=f-Bn%Jx871G5;A@P09+(WyOoYM?Ch|pUN^HWQgHqF94Lx9!$Q2JjE`>2JxRPXZv?k@PigZ@6({MN`a@IMw*s8%Mu^8R6ikhm9S%*| zFJMMMxYr`g!#SMy+rL8Cybtcb4F|LIa7IuL_4BzomY<5lL;92z=H=Ity*|IZ#MNJW eB9Q$!$SC7FG%EiO00030{{sL#`srcW82|vmG=qfz literal 0 HcmV?d00001 From bf05ccaf9d89b52121f13fd97a493385a348dae6 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 01:02:08 +0200 Subject: [PATCH 16/71] Updated composer.lock --- composer.lock | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 3d30aef5..8e465441 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a0fa34d8715378591c16534833ef0d42", + "content-hash": "511121b35d74a4c039929792092b94bf", "packages": [ { "name": "utopia-php/di", @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "833c8e0895d34adda298328cfa17369c6e7792e6" + "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/833c8e0895d34adda298328cfa17369c6e7792e6", - "reference": "833c8e0895d34adda298328cfa17369c6e7792e6", + "url": "https://api.github.com/repos/utopia-php/di/zipball/0bb7af5693bc131f4d2ce34d3f732d41e6637679", + "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-08T19:47:18+00:00" + "time": "2024-04-08T22:41:41+00:00" } ], "packages-dev": [ @@ -3511,6 +3511,8 @@ "php": ">=8.0", "ext-swoole": "*" }, - "platform-dev": [], + "platform-dev": { + "ext-xdebug": "*" + }, "plugin-api-version": "2.6.0" } From 23829ef7dfa4e0a6baf5368d39e9d07e1c079c4b Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 02:07:04 +0200 Subject: [PATCH 17/71] Fixed test --- Dockerfile.swoole | 12 ++++++------ docker-compose.yml | 10 ++-------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Dockerfile.swoole b/Dockerfile.swoole index cfbbaee1..ce4ceb77 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -1,5 +1,11 @@ FROM composer:2.0 AS step0 +ARG TESTING=true +ARG DEBUG=true + +ENV TESTING=$TESTING +ENV DEBUG=$DEBUG + WORKDIR /usr/local/src/ COPY composer.* /usr/local/src/ @@ -12,12 +18,6 @@ FROM appwrite/base:0.9.0 as final LABEL maintainer="team@appwrite.io" -ARG TESTING=true -ARG DEBUG=true - -ENV TESTING=$TESTING -ENV DEBUG=$DEBUG - RUN \ if [ "$DEBUG" == "true" ]; then \ apk add boost boost-dev; \ diff --git a/docker-compose.yml b/docker-compose.yml index 6bed0c7d..45292d0c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: context: . dockerfile: Dockerfile.fpm ports: - - "9020:80" + - "9500:80" volumes: - ./src:/usr/share/nginx/html/src - ./tests:/usr/share/nginx/html/tests @@ -17,7 +17,7 @@ services: context: . dockerfile: Dockerfile.swoole ports: - - "9500:80" + - "9501:80" volumes: - ./dev:/usr/src/code/dev:rw - ./src:/usr/src/code/src @@ -25,11 +25,5 @@ services: - ./tmp/xdebug:/tmp/xdebug networks: - testing - # webgrind: - # image: jokkedk/webgrind:latest - # ports: - # - "9501:80" - # volumes: - # - ./xdebug:/tmp networks: testing: \ No newline at end of file From ea0cfc3f3feed54dbbafc11d9e5c9935a6af5e48 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 19:21:13 +0200 Subject: [PATCH 18/71] Cleanups --- .vscode/launch.json | 2 +- Dockerfile.swoole | 6 ++++++ tmp/xdebug/cachegrind.out.1.gz | Bin 1840 -> 0 bytes 3 files changed, 7 insertions(+), 1 deletion(-) delete mode 100644 tmp/xdebug/cachegrind.out.1.gz diff --git a/.vscode/launch.json b/.vscode/launch.json index 352a0d86..044ea2ae 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,7 +2,7 @@ "name": "Listen for Xdebug", "type": "php", "request": "launch", - "port": 9005, + "port": 9003, "pathMappings": { "/usr/src/code": "${workspaceRoot}" } diff --git a/Dockerfile.swoole b/Dockerfile.swoole index ce4ceb77..f1b0cfb2 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -16,6 +16,12 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ FROM appwrite/base:0.9.0 as final +ARG TESTING=true +ARG DEBUG=true + +ENV TESTING=$TESTING +ENV DEBUG=$DEBUG + LABEL maintainer="team@appwrite.io" RUN \ diff --git a/tmp/xdebug/cachegrind.out.1.gz b/tmp/xdebug/cachegrind.out.1.gz deleted file mode 100644 index a47121d37dada3ffe4a6681b528d957190a81e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1840 zcmV-02haE)iwFP!000000~C!h4udcd1p9l%l~4qS&_sSgnn)D%2+S(61h#c&Ncer6 zZl;+zAnIeV+>#SaIf~`)f_Z;&*K|$GRsZPuUa+glZHr~Is~8n$TwGu>G^@c4Mj;2} zqMsO7H0hlvO_KlN6xHW4QOm0jAi{x=iw%CmShd%nH9xUMImc=~OR^^V0RRC1|EyU} zZ`?Kzz3W%-7$4l#@KanM27)w21N79i=*7T7*2=b8S=vh4ByEuY-XSGQD@s}^Z7;U5 zI~>lunfHdIAM@9*=ndJO>uOh5$u236>F#4%9Loy-emRwOTJ7Rbfvs)%#D0c}6q*Qfk&vHB^i z(I}vTK*R_Sqt*jk%i?Vw*Y!{6Bdz)zSf9gM`2K1jB6Pvi8|#eUkhh)rn=ah6dS7Hs z`gnvSlr(-wQhF2+aUMUgh(#(%X!t<)dt-aCL!b$z8W;f~K+_;;6U5&|`#a9_`ZW*} z0nm#`pp8Uy$Q?5T^CbOPuR((z6V9u4rb;U}~Y)HYkS^{`|9yovlCNvSE=adrz>T3p$ zP(V_JAx?#kQ_>d%^T&@(bFx2rIiNT*vLeaP$B7b57Xb1C{B*=zI-N_K1Xn0~D#S`^ zMQPU?(xu|b16R@9ChJGK{s0;<&hWILCZKr=%D6E73J5Pq-&XjxCI!&4OTkkH+tK*t zR1Iw34e59s#wokNdb+eETB1Fh>gKz0e^3Fk9^p++v|W_%NWn{)q4dwW&SY z%>K8EZt0H6x$WOKM+?nrbIjn>H3!?)9AK|Ht~op($gs}2S~$v~?47ds7KM0s%GzmCM*WTpJ~yIzinx`pl7NZWLS- zXp73KGy@2%p$*Ay7A?=dvixH}D%vpn+yeA(j==u8oO<^Tg(ucfDh!76S@^h&Fjfp$ zcNdt*dGdK>CLxtbLusx}b0|_PSL;*GOv6nxPH5BQ)Ks|LP%k3+b9rvk0ZP3N<*)+z zh8SojuVX1NbEb`K$l;A_1g4}4$G6s^W4U&oe8E60B}AwQluiocT5{WwfoT-QO<)4$ z0tX_aTuX;$`(}sd|6eT!?+q~b7MR<+Q`|fU$~-Rg)4(l&*#(!cSX?8Y3>cD+p*$BNy*hQGO1nGqWQ)|j2rHRwT zs0)XA;UEcb?=q`U0SN3+X_{3yT9~)2anm&^UUGIRO?P;gY=+lTe*N-0vkdRPN@CwQ zx(YXw{EA~wTV|_}OMhf~FkRehuiJH(-0MbkixHa+Oz;HTU3;%q*o;fO)tJ{f#khBv zXLMo=f-Bn%Jx871G5;A@P09+(WyOoYM?Ch|pUN^HWQgHqF94Lx9!$Q2JjE`>2JxRPXZv?k@PigZ@6({MN`a@IMw*s8%Mu^8R6ikhm9S%*| zFJMMMxYr`g!#SMy+rL8Cybtcb4F|LIa7IuL_4BzomY<5lL;92z=H=Ity*|IZ#MNJW eB9Q$!$SC7FG%EiO00030{{sL#`srcW82|vmG=qfz From 5a5fd25c30bf683346d7792274ef3b09c9166ad5 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 21:55:08 +0200 Subject: [PATCH 19/71] Updated composer --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 2fb1cb7a..4bff1bc6 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,6 @@ "upf" ], "license": "MIT", - "minimum-stability": "stable", "autoload": { "psr-4": { "Utopia\\": "src/", From b76d4155bcd0261e68320302a8c69ffddb6741c5 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 22:28:20 +0200 Subject: [PATCH 20/71] Added more tests --- docker-compose.yml | 4 ++-- tests/e2e/BaseTest.php | 6 ++++-- tests/e2e/init.php | 11 ++++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 45292d0c..190a670f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: context: . dockerfile: Dockerfile.fpm ports: - - "9500:80" + - "9400:80" volumes: - ./src:/usr/share/nginx/html/src - ./tests:/usr/share/nginx/html/tests @@ -17,7 +17,7 @@ services: context: . dockerfile: Dockerfile.swoole ports: - - "9501:80" + - "9401:80" volumes: - ./dev:/usr/src/code/dev:rw - ./src:/usr/src/code/src diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index 1c776166..beb1a3ce 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -55,9 +55,11 @@ public function testRedirect() $this->assertEquals('Hello World!', $response['body']); } - public function testFile() + public function testHumans() { $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); - $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEquals('humans.txt', $response['body']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Utopia', $response['headers']['x-engine']); } } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 9cf9a389..27950017 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -13,6 +13,13 @@ ini_set('display_socket_timeout', '-1'); error_reporting(E_ALL); +Http::init() + ->inject('response') + ->action(function ($response) { + $response->addHeader('X-Engine', 'Utopia'); + }); + + Http::wildcard() ->inject('response') ->action(function ($response) { @@ -69,7 +76,9 @@ Http::get('/humans.txt') ->inject('response') ->action(function (Response $response) { - $response->noContent(); + $response + ->setStatusCode(200) + ->text('humans.txt'); }); Http::delete('/no-content') From 0bfe44c347fbabcae6b1936dea8d10e270f0d033 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Tue, 9 Apr 2024 22:44:04 +0200 Subject: [PATCH 21/71] Deprecated request hooks --- src/Http/Http.php | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 26bf13a6..934f4962 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -80,13 +80,6 @@ class Http */ protected static array $startHooks = []; - /** - * Request hooks - * - * @var Hook[] - */ - protected static array $requestHooks = []; - /** * Route * @@ -468,13 +461,6 @@ public static function onStart(): Hook return $hook; } - public static function onRequest(): Hook - { - $hook = new Hook(); - self::$requestHooks[] = $hook; - return $hook; - } - public function start() { $this->server->onRequest(function ($request, $response) { @@ -705,30 +691,6 @@ public function run(Container $context): static $request = $context->get('request'); /** @var Request $request */ $response = $context->get('response'); /** @var Response $response */ - try { - foreach (self::$requestHooks as $hook) { - $this->prepare($context, $hook)->inject($hook, true); - } - } catch(\Exception $e) { - $dependency = new Dependency(); - $context->set( - $dependency - ->setName('error') - ->setCallback(fn () => $e) - ) - ; - - foreach (self::$errors as $error) { // Global error hooks - if (in_array('*', $error->getGroups())) { - try { - $this->prepare($context, $error)->inject($hook, true); - } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); - } - } - } - } - if ($this->isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From cde62b85b1479214d44c4380577f5fe849fb50f5 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Wed, 10 Apr 2024 00:11:14 +0200 Subject: [PATCH 22/71] Test public swoole --- src/Http/Adapter/Swoole/Request.php | 2 +- src/Http/Adapter/Swoole/Response.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Adapter/Swoole/Request.php b/src/Http/Adapter/Swoole/Request.php index 9e319657..9e0ffa11 100644 --- a/src/Http/Adapter/Swoole/Request.php +++ b/src/Http/Adapter/Swoole/Request.php @@ -12,7 +12,7 @@ class Request extends UtopiaRequest * * @var SwooleRequest */ - protected SwooleRequest $swoole; + public SwooleRequest $swoole; /** * Request constructor. diff --git a/src/Http/Adapter/Swoole/Response.php b/src/Http/Adapter/Swoole/Response.php index fd22a62f..515fd103 100644 --- a/src/Http/Adapter/Swoole/Response.php +++ b/src/Http/Adapter/Swoole/Response.php @@ -12,7 +12,7 @@ class Response extends UtopiaResponse * * @var SwooleResponse */ - protected $swoole; + public $swoole; /** * Response constructor. From 524f5d499c5ed3bff2cd9dd4146d063ca779e52b Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Wed, 10 Apr 2024 05:52:59 +0200 Subject: [PATCH 23/71] Updated lock file --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 8e465441..fe3851f1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "511121b35d74a4c039929792092b94bf", + "content-hash": "9fb7534dc954b1f29c6d74dbfcf1a296", "packages": [ { "name": "utopia-php/di", From 5434c04f63f907d860e8ff32e33f9c6af1227ffd Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Wed, 10 Apr 2024 07:39:39 +0200 Subject: [PATCH 24/71] Updated tests --- composer.json | 3 +-- phpunit.xml | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4bff1bc6..b456ad28 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,7 @@ "license": "MIT", "autoload": { "psr-4": { - "Utopia\\": "src/", - "Tests\\E2E\\": "tests/e2e" + "Utopia\\": "src/" } }, "scripts": { diff --git a/phpunit.xml b/phpunit.xml index c87db0dc..c0e0d922 100755 --- a/phpunit.xml +++ b/phpunit.xml @@ -10,6 +10,7 @@ > + ./tests/e2e/init.php ./tests/e2e/Client.php ./tests/MockRequest.php ./tests/MockResponse.php From 1221d45bee36ad5e2caffa488ac7a9a8d5698082 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Wed, 10 Apr 2024 07:56:38 +0200 Subject: [PATCH 25/71] Updated tests --- composer.json | 5 +++++ phpunit.xml | 1 - tests/HttpTest.php | 21 +++++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index b456ad28..e8a29456 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,11 @@ "Utopia\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "Tests\\E2E\\": "tests/e2e" + } + }, "scripts": { "lint": "vendor/bin/pint --test", "format": "vendor/bin/pint", diff --git a/phpunit.xml b/phpunit.xml index c0e0d922..c87db0dc 100755 --- a/phpunit.xml +++ b/phpunit.xml @@ -10,7 +10,6 @@ > - ./tests/e2e/init.php ./tests/e2e/Client.php ./tests/MockRequest.php ./tests/MockResponse.php diff --git a/tests/HttpTest.php b/tests/HttpTest.php index b229375e..36b7f3f8 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -635,14 +635,24 @@ public function testNoMismatchRoute(): void ], ]; - foreach ($requests as $request) { - Http::get($request['path']); - - $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; - $_SERVER['REQUEST_URI'] = $request['url']; + foreach ($requests as $requestObj) { + Http::get($requestObj['path']); $context = clone $this->context; + $request = new Dependency(); + $request + ->setName('request') + ->setCallback(function () use ($requestObj) { + $_SERVER['REQUEST_METHOD'] = Http::REQUEST_METHOD_GET; + $_SERVER['REQUEST_URI'] = $requestObj['url']; + return new Request(); + }); + + $context + ->set($request) + ; + $this->http->run($context); $this->assertEquals(null, $context->get('route')); @@ -662,7 +672,6 @@ public function testCanRunRequest(): void $context = clone $this->context; - $request = new Dependency(); $request ->setName('request') From 995dacb03b571e3b233661593c932fce6b1dc0ff Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 11 Apr 2024 08:14:43 +0200 Subject: [PATCH 26/71] Added test logs --- src/Http/Http.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 934f4962..5f8a783d 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -475,6 +475,8 @@ public function start() $response = new $this->responseClass($response); } + var_dump('start req/res set'); + $context = clone $this->container; $context->set( @@ -489,6 +491,8 @@ public function start() ) ; + var_dump('end req/res set'); + $this->run($context); }); @@ -557,10 +561,12 @@ public function match(Request $request): ?Route */ protected function lifecycle(Route $route, Request $request, Container $context): static { + var_dump('start lifecycle'); $groups = $route->getGroups(); $pathValues = $route->getPathValues($request); try { + var_dump('start global init hooks'); if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { @@ -569,6 +575,7 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } + var_dump('start group init hooks'); foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { @@ -577,8 +584,10 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } + var_dump('start route hook'); $this->prepare($context, $route, $pathValues, $request->getParams())->inject($route, true); + var_dump('start group shutdown hooks'); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array($group, $hook->getGroups())) { @@ -587,6 +596,7 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } + var_dump('start global shutdown hooks'); if ($route->getHook()) { foreach (self::$shutdown as $hook) { // Global shutdown hooks if (in_array('*', $hook->getGroups())) { @@ -603,24 +613,26 @@ protected function lifecycle(Route $route, Request $request, Container $context) ) ; + var_dump('route group error block'); foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks if (in_array($group, $error->getGroups())) { try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); + throw new Exception('Group error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } } + var_dump('global error block'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); + throw new Exception('Global error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } } } @@ -691,6 +703,7 @@ public function run(Container $context): static $request = $context->get('request'); /** @var Request $request */ $response = $context->get('response'); /** @var Response $response */ + var_dump('start check file loaded'); if ($this->isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache @@ -702,11 +715,14 @@ public function run(Container $context): static return $this; } + var_dump('end check file loaded'); $method = $request->getMethod(); $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; + var_dump('end route match'); + var_dump('check wildcard route'); if (null === $route && null !== self::$wildcardRoute) { $route = self::$wildcardRoute; $path = \parse_url($request->getURI(), PHP_URL_PATH); @@ -719,12 +735,15 @@ public function run(Container $context): static ->setName('route') ->setCallback(fn () => $route) ); + var_dump('start set route as DI'); + var_dump('start head check'); if (self::REQUEST_METHOD_HEAD == $method) { $method = self::REQUEST_METHOD_GET; $response->disablePayload(); } + var_dump('start options check'); if (self::REQUEST_METHOD_OPTIONS == $method) { try { foreach ($groups as $group) { @@ -765,6 +784,7 @@ public function run(Container $context): static if (null !== $route) { return $this->lifecycle($route, $request, $context); } elseif (self::REQUEST_METHOD_OPTIONS == $method) { + var_dump('options block'); try { foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks @@ -780,6 +800,7 @@ public function run(Container $context): static } } } catch (\Throwable $e) { + var_dump('global errors hook'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); @@ -795,6 +816,7 @@ public function run(Container $context): static } } } else { + var_dump('error block for not found'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); From bb1421acc92b0fd172fd45d5419e150537268879 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 11 Apr 2024 23:29:35 +0200 Subject: [PATCH 27/71] Removed logs --- src/Http/Http.php | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 5f8a783d..371d158d 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -475,8 +475,6 @@ public function start() $response = new $this->responseClass($response); } - var_dump('start req/res set'); - $context = clone $this->container; $context->set( @@ -491,8 +489,6 @@ public function start() ) ; - var_dump('end req/res set'); - $this->run($context); }); @@ -561,12 +557,10 @@ public function match(Request $request): ?Route */ protected function lifecycle(Route $route, Request $request, Container $context): static { - var_dump('start lifecycle'); $groups = $route->getGroups(); $pathValues = $route->getPathValues($request); try { - var_dump('start global init hooks'); if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { @@ -575,7 +569,6 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } - var_dump('start group init hooks'); foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { @@ -584,10 +577,8 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } - var_dump('start route hook'); $this->prepare($context, $route, $pathValues, $request->getParams())->inject($route, true); - var_dump('start group shutdown hooks'); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks if (in_array($group, $hook->getGroups())) { @@ -596,7 +587,6 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } - var_dump('start global shutdown hooks'); if ($route->getHook()) { foreach (self::$shutdown as $hook) { // Global shutdown hooks if (in_array('*', $hook->getGroups())) { @@ -613,7 +603,6 @@ protected function lifecycle(Route $route, Request $request, Container $context) ) ; - var_dump('route group error block'); foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks if (in_array($group, $error->getGroups())) { @@ -626,7 +615,6 @@ protected function lifecycle(Route $route, Request $request, Container $context) } } - var_dump('global error block'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { @@ -703,7 +691,6 @@ public function run(Container $context): static $request = $context->get('request'); /** @var Request $request */ $response = $context->get('response'); /** @var Response $response */ - var_dump('start check file loaded'); if ($this->isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache @@ -715,14 +702,11 @@ public function run(Container $context): static return $this; } - var_dump('end check file loaded'); $method = $request->getMethod(); $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; - var_dump('end route match'); - var_dump('check wildcard route'); if (null === $route && null !== self::$wildcardRoute) { $route = self::$wildcardRoute; $path = \parse_url($request->getURI(), PHP_URL_PATH); @@ -735,15 +719,12 @@ public function run(Container $context): static ->setName('route') ->setCallback(fn () => $route) ); - var_dump('start set route as DI'); - var_dump('start head check'); if (self::REQUEST_METHOD_HEAD == $method) { $method = self::REQUEST_METHOD_GET; $response->disablePayload(); } - var_dump('start options check'); if (self::REQUEST_METHOD_OPTIONS == $method) { try { foreach ($groups as $group) { @@ -784,7 +765,6 @@ public function run(Container $context): static if (null !== $route) { return $this->lifecycle($route, $request, $context); } elseif (self::REQUEST_METHOD_OPTIONS == $method) { - var_dump('options block'); try { foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks @@ -800,7 +780,6 @@ public function run(Container $context): static } } } catch (\Throwable $e) { - var_dump('global errors hook'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); @@ -816,7 +795,6 @@ public function run(Container $context): static } } } else { - var_dump('error block for not found'); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); From ac7940b37c21136d15496a93b9a87d0e3162c4f7 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 12 Apr 2024 21:42:29 +0200 Subject: [PATCH 28/71] Added DBPool test --- Dockerfile.swoole | 8 +++---- docker-compose.yml | 15 +++++++++++++ src/Http/Adapter/Swoole/Server.php | 36 +++++++++++++----------------- tests/e2e/init.php | 19 ++++++++++++++++ tests/e2e/server-swoole.php | 22 ++++++++++++++++-- tests/k6/benchmark.js | 10 ++++++--- 6 files changed, 81 insertions(+), 29 deletions(-) diff --git a/Dockerfile.swoole b/Dockerfile.swoole index f1b0cfb2..f2267a55 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -1,7 +1,7 @@ FROM composer:2.0 AS step0 -ARG TESTING=true -ARG DEBUG=true +ARG TESTING=false +ARG DEBUG=false ENV TESTING=$TESTING ENV DEBUG=$DEBUG @@ -16,8 +16,8 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ FROM appwrite/base:0.9.0 as final -ARG TESTING=true -ARG DEBUG=true +ARG TESTING=false +ARG DEBUG=false ENV TESTING=$TESTING ENV DEBUG=$DEBUG diff --git a/docker-compose.yml b/docker-compose.yml index 190a670f..744621f0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,5 +25,20 @@ services: - ./tmp/xdebug:/tmp/xdebug networks: - testing + + mariadb: + image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p + container_name: mariadb + networks: + - testing + ports: + - "3307:3306" + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=test + - MYSQL_USER=user + - MYSQL_PASSWORD=password + command: "mysqld --innodb-flush-method=fsync --max-connections=10000" + networks: testing: \ No newline at end of file diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 5c6c0619..d593b6aa 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -2,11 +2,11 @@ namespace Utopia\Http\Adapter\Swoole; -use Swoole\Coroutine; +use PDO; +use PDOException; use Utopia\Http\Adapter; -use Swoole\Coroutine\Http\Server as SwooleServer; -use Swoole\Http\Request as SwooleRequest; -use Swoole\Http\Response as SwooleResponse; +use Swoole\Http\Server as SwooleServer; +use Swoole\Runtime; use function Swoole\Coroutine\run; @@ -24,25 +24,24 @@ public function __construct(string $host, string $port = null, array $settings = // 'http_compression_level' => 6, // Server - // 'log_level' => 2, - 'dispatch_mode' => 3, - 'worker_num' => $workerNumber, - 'reactor_num' => swoole_cpu_num() * 2, - 'task_worker_num' => $workerNumber, - 'open_cpu_affinity' => true, + // 'log_level' => 0, + 'dispatch_mode' => 2, + // 'worker_num' => $workerNumber, + // 'reactor_num' => swoole_cpu_num() * 2, + // 'task_worker_num' => $workerNumber, + // 'open_cpu_affinity' => true, // Coroutine - 'enable_coroutine' => true, - 'max_coroutine' => 300000, + // 'enable_coroutine' => true, + // 'max_coroutine' => 1000, ])); } public function onRequest(callable $callback) { - $this->server->handle('/', function (SwooleRequest $request, SwooleResponse $response) use ($callback) { + + $this->server->on('request', function ($request, $response) use ($callback) { call_user_func($callback, new Request($request), new Response($response)); - // go(function () use ($request, $response, $callback) { - // }); }); } @@ -53,10 +52,7 @@ public function onStart(callable $callback) public function start() { - if(Coroutine::getCid() === -1) { - run(fn () => $this->server->start()); - } else { - $this->server->start(); - } + Runtime::enableCoroutine(); + return $this->server->start(); } } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 27950017..f0205b0b 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../../vendor/autoload.php'; use Swoole\Coroutine\System; +use Swoole\Database\PDOPool; use Utopia\Http\Http; use Utopia\Http\Response; use Utopia\Http\Validator\Text; @@ -87,6 +88,24 @@ $response->noContent(); }); +Http::get('/db-ping') + ->inject('pool') + ->inject('response') + ->action(function (PDOPool $pool, Response $response) { + $pdo = $pool->get(); + + $statement = $pdo->query('SELECT 1;'); + $output = ''; + while ($row = $statement->fetch()) { + // var_dump('worked!'); + $output .= $row[0]; + } + + $pool->put($pdo); + + $response->send($output); + }); + Http::error() ->inject('error') ->inject('response') diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index fb7193d0..223af7a5 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -2,14 +2,23 @@ require_once __DIR__.'/init.php'; -use Swoole\Runtime; +use Swoole\Database\PDOConfig; +use Swoole\Database\PDOPool; use Utopia\DI\Container; use Utopia\DI\Dependency; use Utopia\Http\Request; use Utopia\Http\Adapter\Swoole\Server; use Utopia\Http\Http; -Runtime::enableCoroutine(SWOOLE_HOOK_ALL); +$pool = new PDOPool((new PDOConfig) + ->withHost('mariadb') + ->withPort(3306) + // ->withUnixSocket('/tmp/mysql.sock') + ->withDbName('test') + ->withCharset('utf8mb4') + ->withUsername('user') + ->withPassword('password') +, 9000); $container = new Container(); @@ -24,6 +33,15 @@ $container->set($dependency); +$dependency1 = new Dependency(); +$dependency1 + ->setName('pool') + ->setCallback(function () use ($pool) { + return $pool; + }); + +$container->set($dependency1); + $server = new Server('0.0.0.0', '80'); $http = new Http($server, $container, 'UTC'); diff --git a/tests/k6/benchmark.js b/tests/k6/benchmark.js index e87d69d3..f9946a8f 100644 --- a/tests/k6/benchmark.js +++ b/tests/k6/benchmark.js @@ -9,11 +9,11 @@ export const options = { scenarios: { contacts: { executor: 'ramping-arrival-rate', - preAllocatedVUs: 100, + preAllocatedVUs: 1000, timeUnit: '30s', startRate: 1000000, stages: [ - { target: 1000000, duration: '1m' }, + { target: 1000000, duration: '10m' }, ], }, }, @@ -32,7 +32,11 @@ export default function () { } }; - const resDb = http.get('http://localhost:9500/', config); + const resDb = http.get('http://localhost:9401', config); + + if(resDb.status !== 200) { + console.log(`Error: ${resDb.status}`); + } check(resDb, { 'status is 200': (r) => r.status === 200, From 08e70ee3b3f3967e97744945869a5ad458c36207 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 14:56:22 +0200 Subject: [PATCH 29/71] Test --- src/Http/Adapter/Swoole/Server.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index d593b6aa..5f60630f 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -41,7 +41,9 @@ public function onRequest(callable $callback) { $this->server->on('request', function ($request, $response) use ($callback) { - call_user_func($callback, new Request($request), new Response($response)); + go(function () use ($request, $response, $callback) { + call_user_func($callback, new Request($request), new Response($response)); + }); }); } From efb7331a5ad43feeb71b9c3502c8d4b30e22864f Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 18:59:00 +0200 Subject: [PATCH 30/71] Isolated server start context --- src/Http/Adapter/Swoole/Server.php | 3 --- src/Http/Http.php | 9 +++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 5f60630f..908b3d1a 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -2,8 +2,6 @@ namespace Utopia\Http\Adapter\Swoole; -use PDO; -use PDOException; use Utopia\Http\Adapter; use Swoole\Http\Server as SwooleServer; use Swoole\Runtime; @@ -39,7 +37,6 @@ public function __construct(string $host, string $port = null, array $settings = public function onRequest(callable $callback) { - $this->server->on('request', function ($request, $response) use ($callback) { go(function () use ($request, $response, $callback) { call_user_func($callback, new Request($request), new Response($response)); diff --git a/src/Http/Http.php b/src/Http/Http.php index 371d158d..0e68f96f 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -493,9 +493,10 @@ public function start() }); $this->server->onStart(function ($server) { + $container = clone $this->container; $dependency = new Dependency(); - $this->container + $container ->set( $dependency ->setName('server') @@ -505,12 +506,12 @@ public function start() try { foreach (self::$startHooks as $hook) { - $this->prepare($this->container, $hook, [], [])->inject($hook, true); + $this->prepare($container, $hook, [], [])->inject($hook, true); } } catch(\Exception $e) { $dependency = new Dependency(); - $this->container->set( + $container->set( $dependency ->setName('error') ->setCallback(fn () => $e) @@ -520,7 +521,7 @@ public function start() foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { - $this->prepare($this->container, $error, [], [])->inject($error, true); + $this->prepare($container, $error, [], [])->inject($error, true); } catch (\Throwable $e) { throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); } From 22e634e5e67a34b823411e5ae376dced1c762e1b Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 19:10:02 +0200 Subject: [PATCH 31/71] Run event in coroutine --- src/Http/Adapter/Swoole/Server.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 908b3d1a..ae1dd4a4 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -46,7 +46,11 @@ public function onRequest(callable $callback) public function onStart(callable $callback) { - call_user_func($callback, $this); + $this->server->on('request', function () use ($callback) { + go(function () use ($callback) { + call_user_func($callback, $this); + }); + }); } public function start() From b303e29b400498f163fc36fb10b2e855017f0917 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 19:12:12 +0200 Subject: [PATCH 32/71] Fixed typo --- src/Http/Adapter/Swoole/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index ae1dd4a4..9c96e41f 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -46,7 +46,7 @@ public function onRequest(callable $callback) public function onStart(callable $callback) { - $this->server->on('request', function () use ($callback) { + $this->server->on('start', function () use ($callback) { go(function () use ($callback) { call_user_func($callback, $this); }); From 1d8ced99a7c13b1cb7fbc74b442d609973555bf6 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 19:15:09 +0200 Subject: [PATCH 33/71] Fixed callback --- src/Http/Adapter/Swoole/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 9c96e41f..4cdc93b2 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -48,7 +48,7 @@ public function onStart(callable $callback) { $this->server->on('start', function () use ($callback) { go(function () use ($callback) { - call_user_func($callback, $this); + call_user_func($callback); }); }); } From aef4e9a7bcb3ba21b993f2daad0364657c2fe1aa Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sat, 13 Apr 2024 19:20:36 +0200 Subject: [PATCH 34/71] Fixed arg count --- src/Http/Http.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 0e68f96f..7943dad1 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -492,7 +492,7 @@ public function start() $this->run($context); }); - $this->server->onStart(function ($server) { + $this->server->onStart(function () { $container = clone $this->container; $dependency = new Dependency(); @@ -500,7 +500,7 @@ public function start() ->set( $dependency ->setName('server') - ->setCallback(fn () => $server) + ->setCallback(fn () => $this->server) ) ; From d600ae234780e083c600ab62a8348b7ea506cd1d Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sun, 14 Apr 2024 18:41:37 +0200 Subject: [PATCH 35/71] Fixed bug with params --- src/Http/Http.php | 2 +- tests/e2e/BaseTest.php | 11 +++++++++++ tests/e2e/init.php | 26 +++++++++++++++++++++++--- tests/e2e/server-fpm.php | 11 ++++++++--- tests/e2e/server-swoole.php | 7 +++++-- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 7943dad1..4e1da7a9 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -837,7 +837,7 @@ protected function validate(string $key, array $param, mixed $value, Container $ $dependency = new Dependency(); $dependency - ->setName($key) + ->setName('_validator:'.$key) ->setCallback($param['validator']) ; diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index beb1a3ce..c6ff763a 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -62,4 +62,15 @@ public function testHumans() $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('Utopia', $response['headers']['x-engine']); } + + public function testParamInjection() + { + $response = $this->client->call(Client::METHOD_GET, '/param-injection?param=1234567891011'); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringStartsWith('Invalid `param` param: Value must be a valid string and at least 1 chars and no longer than 10 chars', $response['body']); + + $response = $this->client->call(Client::METHOD_GET, '/param-injection?param=test4573'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringStartsWith('Hello World!test4573', $response['body']); + } } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index f0205b0b..21019013 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -1,9 +1,8 @@ setName('num') + ->setCallback(function () { + return 10; + }); + +$container->set($dependency); + Http::init() ->inject('response') ->action(function ($response) { @@ -106,9 +117,18 @@ $response->send($output); }); +Http::get('/param-injection') + ->inject('response') + ->param('param', 'default', fn($num) => new Text($num), 'test param', false, ['num']) + ->action(function (Response $response, string $param) { + $response->send('Hello World!' . $param); + }); + Http::error() ->inject('error') ->inject('response') ->action(function (Throwable $error, Response $response) { - $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); + $response + ->setStatusCode($error->getCode()) + ->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); }); diff --git a/tests/e2e/server-fpm.php b/tests/e2e/server-fpm.php index 8e889754..75f285a4 100644 --- a/tests/e2e/server-fpm.php +++ b/tests/e2e/server-fpm.php @@ -1,11 +1,16 @@ start(); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 223af7a5..2f3d1eda 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -1,6 +1,6 @@ withHost('mariadb') ->withPort(3306) @@ -20,7 +24,6 @@ ->withPassword('password') , 9000); -$container = new Container(); $dependency = new Dependency(); From 5905398705d667ca66208f815f97fea9b3840825 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sun, 14 Apr 2024 20:44:18 +0200 Subject: [PATCH 36/71] Always return Route, added not found test --- src/Http/Http.php | 2 +- tests/HttpTest.php | 3 ++- tests/e2e/BaseTest.php | 7 +++++++ tests/e2e/init.php | 10 +++++----- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 4e1da7a9..73fe8d85 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -718,7 +718,7 @@ public function run(Container $context): static $context->set( $dependency ->setName('route') - ->setCallback(fn () => $route) + ->setCallback(fn () => $route ?? new Route($request->getMethod(), $request->getURI())) ); if (self::REQUEST_METHOD_HEAD == $method) { diff --git a/tests/HttpTest.php b/tests/HttpTest.php index 36b7f3f8..eca9f871 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -655,7 +655,8 @@ public function testNoMismatchRoute(): void $this->http->run($context); - $this->assertEquals(null, $context->get('route')); + $this->assertEquals($_SERVER['REQUEST_METHOD'], $context->get('route')->getMethod()); + $this->assertEquals($_SERVER['REQUEST_URI'], $context->get('route')->getPath()); } } diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index c6ff763a..e04c4016 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -73,4 +73,11 @@ public function testParamInjection() $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringStartsWith('Hello World!test4573', $response['body']); } + + public function testNotFound() + { + $response = $this->client->call(Client::METHOD_GET, '/non-existing-page'); + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringStartsWith('Not Found on ', $response['body']); + } } diff --git a/tests/e2e/init.php b/tests/e2e/init.php index 21019013..f5e736dd 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -32,11 +32,11 @@ }); -Http::wildcard() - ->inject('response') - ->action(function ($response) { - $response->send('WILDCARD'); - }); +// Http::wildcard() +// ->inject('response') +// ->action(function ($response) { +// $response->send('WILDCARD'); +// }); Http::get('/') ->inject('response') From 9b0916fc02aa1e9d908127c2cc9c6277bb534091 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:21:24 +0200 Subject: [PATCH 37/71] Test base server --- composer.json | 7 +- composer.lock | 567 +++++++++++++++++++++++++++-------------- src/Http/Exception.php | 4 +- src/Http/Hook.php | 249 +----------------- src/Http/Http.php | 270 +------------------- src/Http/Validator.php | 55 +--- 6 files changed, 400 insertions(+), 752 deletions(-) diff --git a/composer.json b/composer.json index e8a29456..9244c0a6 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "upf" ], "license": "MIT", + "minimum-stability": "dev", "autoload": { "psr-4": { "Utopia\\": "src/" @@ -29,7 +30,7 @@ "require": { "php": ">=8.0", "ext-swoole": "*", - "utopia-php/di": "dev-main" + "utopia-php/servers": "dev-dev" }, "require-dev": { "ext-xdebug": "*", @@ -40,6 +41,10 @@ "phpbench/phpbench": "^1.2" }, "repositories": [ + { + "type": "vcs", + "url": "https://github.com/utopia-php/servers" + }, { "type": "vcs", "url": "https://github.com/utopia-php/di" diff --git a/composer.lock b/composer.lock index fe3851f1..46f4edf6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,69 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9fb7534dc954b1f29c6d74dbfcf1a296", + "content-hash": "f961290f450cd8657302383ece07a86b", "packages": [ + { + "name": "utopia-php/cli", + "version": "0.17.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/cli.git", + "reference": "0829fd5215afe88f53f3091cedc808da801fd1bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/cli/zipball/0829fd5215afe88f53f3091cedc808da801fd1bb", + "reference": "0829fd5215afe88f53f3091cedc808da801fd1bb", + "shasum": "" + }, + "require": { + "php": ">=7.4", + "utopia-php/framework": "0.34.*" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.6", + "vimeo/psalm": "4.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\CLI\\": "src/CLI" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A simple CLI library to manage command line applications", + "keywords": [ + "cli", + "command line", + "framework", + "php", + "upf", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/cli/issues", + "source": "https://github.com/utopia-php/cli/tree/0.17.0" + }, + "time": "2024-01-24T11:37:29+00:00" + }, { "name": "utopia-php/di", "version": "dev-main", "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679" + "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/0bb7af5693bc131f4d2ce34d3f732d41e6637679", - "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679", + "url": "https://api.github.com/repos/utopia-php/di/zipball/fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", + "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", "shasum": "" }, "require": { @@ -66,22 +115,142 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-08T22:41:41+00:00" + "time": "2024-04-18T20:06:02+00:00" + }, + { + "name": "utopia-php/framework", + "version": "0.34.2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/http.git", + "reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/http/zipball/fd126c02b78cc80678c9638f7b335dfb4a841b78", + "reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78", + "shasum": "" + }, + "require": { + "ext-swoole": "*", + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25", + "swoole/ide-helper": "4.8.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Http\\": "src/Http" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A simple, light and advanced PHP HTTP framework", + "keywords": [ + "framework", + "http", + "php", + "upf" + ], + "support": { + "issues": "https://github.com/utopia-php/http/issues", + "source": "https://github.com/utopia-php/http/tree/0.34.2" + }, + "time": "2024-02-20T11:36:56+00:00" + }, + { + "name": "utopia-php/servers", + "version": "dev-dev", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/servers.git", + "reference": "afde8000e4d87ab1bb3cceba1c17e2506292123a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/afde8000e4d87ab1bb3cceba1c17e2506292123a", + "reference": "afde8000e4d87ab1bb3cceba1c17e2506292123a", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "utopia-php/cli": "0.17.*", + "utopia-php/di": "dev-main" + }, + "require-dev": { + "laravel/pint": "^0.2.3", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Queue\\": "src/Servers" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\E2E\\": "tests/Servers/Unit" + } + }, + "scripts": { + "test": [ + "phpunit" + ], + "analyse": [ + "vendor/bin/phpstan analyse" + ], + "format": [ + "vendor/bin/pint" + ], + "lint": [ + "vendor/bin/pint --test" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Team Appwrite", + "email": "team@appwrite.io" + } + ], + "description": "A base library for building Utopia style servers.", + "keywords": [ + "framework", + "php", + "servers", + "upf", + "utopia" + ], + "support": { + "source": "https://github.com/utopia-php/servers/tree/dev", + "issues": "https://github.com/utopia-php/servers/issues" + }, + "time": "2024-04-18T20:05:13+00:00" } ], "packages-dev": [ { "name": "doctrine/annotations", - "version": "2.0.1", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" + "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/94f40ad7ecbc6931958faa8a57c48dce5da2b468", + "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468", "shasum": "" }, "require": { @@ -101,6 +270,7 @@ "suggest": { "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -142,37 +312,38 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" + "source": "https://github.com/doctrine/annotations/tree/2.0.x" }, - "time": "2023-02-02T22:02:53+00:00" + "time": "2023-08-23T17:36:07+00:00" }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", + "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^12", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", "phpstan/phpstan": "^1.9.4", "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", + "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.4" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -198,7 +369,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.x" }, "funding": [ { @@ -214,20 +385,20 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2023-12-09T14:19:21+00:00" }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "3.1.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", + "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", "shasum": "" }, "require": { @@ -275,7 +446,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/3.1.x" }, "funding": [ { @@ -291,7 +462,7 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2024-02-05T12:02:27+00:00" }, { "name": "laravel/pint", @@ -361,16 +532,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "2f5294676c802a62b0549f6bc8983f14294ce369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/2f5294676c802a62b0549f6bc8983f14294ce369", + "reference": "2f5294676c802a62b0549f6bc8983f14294ce369", "shasum": "" }, "require": { @@ -378,13 +549,15 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, + "default-branch": true, "type": "library", "autoload": { "files": [ @@ -408,7 +581,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" }, "funding": [ { @@ -416,20 +589,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-02-10T11:10:03+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/46be4560c4cd4bab2b74882c0da39a4548a5cfbe", + "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe", "shasum": "" }, "require": { @@ -440,8 +613,9 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, + "default-branch": true, "bin": [ "bin/php-parse" ], @@ -472,13 +646,13 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/master" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-03-17T10:24:36+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.4", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", @@ -498,6 +672,7 @@ "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -596,7 +771,7 @@ }, { "name": "phpbench/container", - "version": "2.2.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phpbench/container.git", @@ -617,6 +792,7 @@ "phpstan/phpstan": "^0.12.52", "phpunit/phpunit": "^8" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -698,16 +874,16 @@ }, { "name": "phpbench/phpbench", - "version": "1.2.15", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c" + "reference": "c4af952ad3e19cc1a754b98f1ea47a10371e1749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/f7000319695cfad04a57fc64bf7ef7abdf4c437c", - "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c4af952ad3e19cc1a754b98f1ea47a10371e1749", + "reference": "c4af952ad3e19cc1a754b98f1ea47a10371e1749", "shasum": "" }, "require": { @@ -719,33 +895,39 @@ "ext-spl": "*", "ext-tokenizer": "*", "php": "^8.1", - "phpbench/container": "^2.1", + "phpbench/container": "^2.2", "phpbench/dom": "~0.3.3", "psr/log": "^1.1 || ^2.0 || ^3.0", "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0 || ^7.0", + "symfony/console": "^6.1 || ^7.0", + "symfony/filesystem": "^6.1 || ^7.0", + "symfony/finder": "^6.1 || ^7.0", + "symfony/options-resolver": "^6.1 || ^7.0", + "symfony/process": "^6.1 || ^7.0", "webmozart/glob": "^4.6" }, + "replace": { + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*" + }, "require-dev": { "dantleech/invoke": "^2.0", + "ergebnis/composer-normalize": "^2.39", "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", "phpspec/prophecy": "dev-master", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.0", - "rector/rector": "^0.18.10", - "symfony/error-handler": "^5.2 || ^6.0 || ^7.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^10.4", + "rector/rector": "^0.18.11 || ^1.0.0", + "symfony/error-handler": "^6.1 || ^7.0", + "symfony/var-dumper": "^6.1 || ^7.0" }, "suggest": { "ext-xdebug": "For Xdebug profiling extension." }, + "default-branch": true, "bin": [ "bin/phpbench" ], @@ -784,7 +966,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.15" + "source": "https://github.com/phpbench/phpbench/tree/master" }, "funding": [ { @@ -792,20 +974,20 @@ "type": "github" } ], - "time": "2023-11-29T12:21:11+00:00" + "time": "2024-04-10T12:50:15+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.66", + "version": "1.11.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd" + "reference": "1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5", + "reference": "1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5", "shasum": "" }, "require": { @@ -814,6 +996,7 @@ "conflict": { "phpstan/phpstan-shim": "*" }, + "default-branch": true, "bin": [ "phpstan", "phpstan.phar" @@ -848,26 +1031,22 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-28T16:17:31+00:00" + "time": "2024-04-18T15:41:16+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "9.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "3352293d9e91513d5508c415835014881b420218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/3352293d9e91513d5508c415835014881b420218", + "reference": "3352293d9e91513d5508c415835014881b420218", "shasum": "" }, "require": { @@ -924,7 +1103,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2" }, "funding": [ { @@ -932,20 +1111,20 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-03-22T05:16:32+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/38b24367e1b340aa78b96d7cab042942d917bb84", + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84", "shasum": "" }, "require": { @@ -984,7 +1163,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0" }, "funding": [ { @@ -992,7 +1171,7 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2022-02-11T16:23:04+00:00" }, { "name": "phpunit/php-invoker", @@ -1177,16 +1356,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.19", + "version": "9.6.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + "reference": "2f5cc6727bef6304e013d24e16e2203ca1f5ea94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f5cc6727bef6304e013d24e16e2203ca1f5ea94", + "reference": "2f5cc6727bef6304e013d24e16e2203ca1f5ea94", "shasum": "" }, "require": { @@ -1260,7 +1439,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6" }, "funding": [ { @@ -1276,29 +1455,33 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:35:58+00:00" + "time": "2024-04-18T12:34:34+00:00" }, { "name": "psr/cache", - "version": "3.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "url": "https://api.github.com/repos/php-fig/cache/zipball/0a7c67d0d1c8167b342eb74339d6f961663826ce", + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce", "shasum": "" }, "require": { "php": ">=8.0.0" }, + "suggest": { + "fig/cache-util": "Provides some useful PSR-6 utilities" + }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1323,27 +1506,28 @@ "psr-6" ], "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" + "source": "https://github.com/php-fig/cache/tree/master" }, - "time": "2021-02-03T23:26:27+00:00" + "time": "2021-02-24T03:25:37+00:00" }, { "name": "psr/container", - "version": "2.0.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "707984727bd5b2b670e59559d3ed2500240cf875" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875", "shasum": "" }, "require": { "php": ">=7.4.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1376,13 +1560,13 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2023-09-22T11:11:30+00:00" }, { "name": "psr/log", - "version": "3.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", @@ -1397,6 +1581,7 @@ "require": { "php": ">=8.0.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1432,7 +1617,7 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "1.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", @@ -1599,16 +1784,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b247957a1c8dc81a671770f74b479c0a78a818f1", + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1", "shasum": "" }, "require": { @@ -1661,7 +1846,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0" }, "funding": [ { @@ -1669,11 +1854,11 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2022-09-14T12:46:14+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", @@ -1730,7 +1915,7 @@ }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", @@ -1796,7 +1981,7 @@ }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "5.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", @@ -1847,7 +2032,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1" }, "funding": [ { @@ -1859,7 +2044,7 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", @@ -1936,7 +2121,7 @@ }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", @@ -2000,7 +2185,7 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "1.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", @@ -2169,7 +2354,7 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", @@ -2232,16 +2417,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.4", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", + "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", "shasum": "" }, "require": { @@ -2250,6 +2435,7 @@ "require-dev": { "phpunit/phpunit": "^9.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -2274,7 +2460,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/main" }, "funding": [ { @@ -2282,11 +2468,11 @@ "type": "github" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2024-03-14T18:47:08+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "3.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", @@ -2330,7 +2516,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/3.2" }, "funding": [ { @@ -2342,7 +2528,7 @@ }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", @@ -2501,16 +2687,16 @@ }, { "name": "symfony/console", - "version": "v7.0.6", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" + "reference": "1b84910b638ce3265e132d7b42405b2db64f6f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "url": "https://api.github.com/repos/symfony/console/zipball/1b84910b638ce3265e132d7b42405b2db64f6f69", + "reference": "1b84910b638ce3265e132d7b42405b2db64f6f69", "shasum": "" }, "require": { @@ -2574,7 +2760,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.6" + "source": "https://github.com/symfony/console/tree/7.1" }, "funding": [ { @@ -2590,29 +2776,30 @@ "type": "tidelift" } ], - "time": "2024-04-01T11:04:53+00:00" + "time": "2024-04-06T17:55:56+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/2c438b99bb2753c1628c1e6f523991edea5b03a4", + "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4", "shasum": "" }, "require": { "php": ">=8.1" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -2641,7 +2828,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/main" }, "funding": [ { @@ -2657,26 +2844,27 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-01-02T14:07:37+00:00" }, { "name": "symfony/filesystem", - "version": "v7.0.6", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d" + "reference": "47d346741881ecf75f6b6474b52f0781e6c42af7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/47d346741881ecf75f6b6474b52f0781e6c42af7", + "reference": "47d346741881ecf75f6b6474b52f0781e6c42af7", "shasum": "" }, "require": { "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" + "symfony/polyfill-mbstring": "~1.8", + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2704,7 +2892,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.0.6" + "source": "https://github.com/symfony/filesystem/tree/7.1" }, "funding": [ { @@ -2720,20 +2908,20 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:37:36+00:00" + "time": "2024-04-16T16:29:43+00:00" }, { "name": "symfony/finder", - "version": "v7.0.0", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" + "reference": "9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "url": "https://api.github.com/repos/symfony/finder/zipball/9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03", + "reference": "9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03", "shasum": "" }, "require": { @@ -2768,7 +2956,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.0.0" + "source": "https://github.com/symfony/finder/tree/7.1" }, "funding": [ { @@ -2784,20 +2972,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:59:56+00:00" + "time": "2024-03-20T15:26:56+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.0.0", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f" + "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9564f64c16f99e29f252eafc642965e8fcb755ce", + "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce", "shasum": "" }, "require": { @@ -2835,7 +3023,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.0.0" + "source": "https://github.com/symfony/options-resolver/tree/7.1" }, "funding": [ { @@ -2851,11 +3039,11 @@ "type": "tidelift" } ], - "time": "2023-08-08T10:20:21+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2876,6 +3064,7 @@ "suggest": { "ext-ctype": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -2934,7 +3123,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -2952,6 +3141,7 @@ "suggest": { "ext-intl": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3012,7 +3202,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -3030,6 +3220,7 @@ "suggest": { "ext-intl": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3093,16 +3284,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "3cf95983a25d6439cac5f5164f0bfeeb1eb5d264" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3cf95983a25d6439cac5f5164f0bfeeb1eb5d264", + "reference": "3cf95983a25d6439cac5f5164f0bfeeb1eb5d264", "shasum": "" }, "require": { @@ -3114,6 +3305,7 @@ "suggest": { "ext-mbstring": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3153,7 +3345,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" }, "funding": [ { @@ -3169,20 +3361,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-04-12T09:26:28+00:00" }, { "name": "symfony/process", - "version": "v7.0.4", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9" + "reference": "8e99b1b15d2975b242fc089382c8f8055a85d996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9", + "url": "https://api.github.com/repos/symfony/process/zipball/8e99b1b15d2975b242fc089382c8f8055a85d996", + "reference": "8e99b1b15d2975b242fc089382c8f8055a85d996", "shasum": "" }, "require": { @@ -3214,7 +3406,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.0.4" + "source": "https://github.com/symfony/process/tree/7.1" }, "funding": [ { @@ -3230,33 +3422,35 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-05T09:28:19+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.2", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" + "reference": "a17e69656265139c2ab4a62529f495a2a41fd6ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a17e69656265139c2ab4a62529f495a2a41fd6ce", + "reference": "a17e69656265139c2ab4a62529f495a2a41fd6ce", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3296,7 +3490,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/service-contracts/tree/main" }, "funding": [ { @@ -3312,20 +3506,20 @@ "type": "tidelift" } ], - "time": "2023-12-19T21:51:00+00:00" + "time": "2024-04-05T09:39:30+00:00" }, { "name": "symfony/string", - "version": "v7.0.4", + "version": "7.1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" + "reference": "236b450c00ab6560e6cda684853d2db3c6b41731" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", + "url": "https://api.github.com/repos/symfony/string/zipball/236b450c00ab6560e6cda684853d2db3c6b41731", + "reference": "236b450c00ab6560e6cda684853d2db3c6b41731", "shasum": "" }, "require": { @@ -3339,6 +3533,7 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { + "symfony/emoji": "^7.1", "symfony/error-handler": "^6.4|^7.0", "symfony/http-client": "^6.4|^7.0", "symfony/intl": "^6.4|^7.0", @@ -3382,7 +3577,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.4" + "source": "https://github.com/symfony/string/tree/7.1" }, "funding": [ { @@ -3398,7 +3593,7 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:17:36+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "theseer/tokenizer", @@ -3452,7 +3647,7 @@ }, { "name": "webmozart/glob", - "version": "4.7.0", + "version": "4.8.x-dev", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", @@ -3501,9 +3696,9 @@ } ], "aliases": [], - "minimum-stability": "stable", + "minimum-stability": "dev", "stability-flags": { - "utopia-php/di": 20 + "utopia-php/servers": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/src/Http/Exception.php b/src/Http/Exception.php index 46e55958..4de36cc3 100644 --- a/src/Http/Exception.php +++ b/src/Http/Exception.php @@ -2,6 +2,8 @@ namespace Utopia\Http; -class Exception extends \Exception +use Utopia\Servers\Exception as ServersException; + +class Exception extends ServersException { } diff --git a/src/Http/Hook.php b/src/Http/Hook.php index 6519744e..e83a4f88 100644 --- a/src/Http/Hook.php +++ b/src/Http/Hook.php @@ -2,253 +2,8 @@ namespace Utopia\Http; -use Utopia\DI\Injection; +use Utopia\Servers\Hook as ServersHook; -class Hook extends Injection +class Hook extends ServersHook { - /** - * Description - * - * @var string - */ - protected string $desc = ''; - - /** - * Parameters - * - * List of route params names and validators - * - * @var array - */ - protected array $params = []; - - /** - * Group - * - * @var array - */ - protected array $groups = []; - - /** - * Labels - * - * List of route label names - * - * @var array - */ - protected array $labels = []; - - /** - * Injections - * - * List of route required injections for action callback - * - * @var array - */ - protected array $injections = []; - - /** - * Add Description - * - * @param string $desc - * @return static - */ - public function desc(string $desc): static - { - $this->desc = $desc; - - return $this; - } - - /** - * Get Description - * - * @return string - */ - public function getDesc(): string - { - return $this->desc; - } - - /** - * Add Group - * - * @param array $groups - * @return static - */ - public function groups(array $groups): static - { - $this->groups = $groups; - - return $this; - } - - /** - * Get Groups - * - * @return array - */ - public function getGroups(): array - { - return $this->groups; - } - - /** - * Add Label - * - * @param string $key - * @param mixed $value - * @return $this - */ - public function label(string $key, mixed $value): static - { - $this->labels[$key] = $value; - - return $this; - } - - /** - * Get Label - * - * Return given label value or default value if label doesn't exists - * - * @param string $key - * @param mixed $default - * @return mixed - */ - public function getLabel(string $key, mixed $default): mixed - { - return (isset($this->labels[$key])) ? $this->labels[$key] : $default; - } - - /** - * Add Action - * - * @param callable $action - * @return static - */ - public function action(callable $action): static - { - $this->setCallback($action); - - return $this; - } - - /** - * Get Action - * - * @return callable - */ - public function getAction() - { - return $this->getCallback(); - } - - /** - * Depenedency - * - * @param string $name - * @return self - * - * @throws Exception - */ - public function inject(string $name): self - { - parent::inject($name); - - return $this; - } - - /** - * Add Param - * - * @param string $key - * @param mixed $default - * @param Validator|callable $validator - * @param string $description - * @param bool $optional - * @param array $injections - * @param bool $skipValidation - * @return static - */ - public function param(string $key, mixed $default, Validator|callable $validator, string $description = '', bool $optional = false, array $injections = [], bool $skipValidation = false): static - { - $this->params[$key] = [ - 'default' => $default, - 'validator' => $validator, - 'description' => $description, - 'optional' => $optional, - 'injections' => $injections, - 'skipValidation' => $skipValidation, - 'value' => null, - 'order' => count($this->params) + count($this->injections), - ]; - - $this->inject($key); - - return $this; - } - - /** - * Get Params - * - * @return array - */ - public function getParams(): array - { - return $this->params; - } - - /** - * Get Param Values - * - * @return array - */ - public function getParamsValues(): array - { - $values = []; - - foreach ($this->params as $key => $param) { - $values[$key] = $param['value']; - } - - return $values; - } - - /** - * Set Param Value - * - * @param string $key - * @param mixed $value - * @return static - * - * @throws Exception - */ - public function setParamValue(string $key, mixed $value): static - { - if (!isset($this->params[$key])) { - throw new Exception('Unknown key'); - } - - $this->params[$key]['value'] = $value; - - return $this; - } - - /** - * Get Param Value - * - * @param string $key - * @return mixed - * - * @throws Exception - */ - public function getParamValue(string $key): mixed - { - if (!isset($this->params[$key])) { - throw new Exception('Unknown key'); - } - - return $this->params[$key]['value']; - } } diff --git a/src/Http/Http.php b/src/Http/Http.php index 73fe8d85..00569b20 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -4,8 +4,9 @@ use Utopia\DI\Container; use Utopia\DI\Dependency; +use Utopia\Servers\Base; -class Http +class Http extends Base { /** * Request method constants @@ -18,52 +19,11 @@ class Http public const REQUEST_METHOD_OPTIONS = 'OPTIONS'; public const REQUEST_METHOD_HEAD = 'HEAD'; - /** - * Mode Type - */ - public const MODE_TYPE_DEVELOPMENT = 'development'; - public const MODE_TYPE_STAGE = 'stage'; - public const MODE_TYPE_PRODUCTION = 'production'; - /** * @var Files */ protected Files $files; - /** - * Current running mode - * - * @var string - */ - protected static string $mode = ''; - - /** - * Errors - * - * Errors callbacks - * - * @var Hook[] - */ - protected static array $errors = []; - - /** - * Init - * - * A callback function that is initialized on application start - * - * @var Hook[] - */ - protected static array $init = []; - - /** - * Shutdown - * - * A callback function that is initialized on application end - * - * @var Hook[] - */ - protected static array $shutdown = []; - /** * Options * @@ -73,22 +33,6 @@ class Http */ protected static array $options = []; - /** - * Server Start hooks - * - * @var Hook[] - */ - protected static array $startHooks = []; - - /** - * Route - * - * Memory cached result for chosen route - * - * @var Route|null - */ - protected ?Route $route = null; - /** * Wildcard route * If set, this get's executed if no other route is matched @@ -102,11 +46,6 @@ class Http */ protected Adapter $server; - /** - * @var Container - */ - protected Container $container; - protected string|null $requestClass = null; protected string|null $responseClass = null; @@ -221,40 +160,6 @@ public static function wildcard(): Route return $route; } - /** - * Init - * - * Set a callback function that will be initialized on application start - * - * @return Hook - */ - public static function init(): Hook - { - $hook = new Hook(); - $hook->groups(['*']); - - self::$init[] = $hook; - - return $hook; - } - - /** - * Shutdown - * - * Set a callback function that will be initialized on application end - * - * @return Hook - */ - public static function shutdown(): Hook - { - $hook = new Hook(); - $hook->groups(['*']); - - self::$shutdown[] = $hook; - - return $hook; - } - /** * Options * @@ -272,23 +177,6 @@ public static function options(): Hook return $hook; } - /** - * Error - * - * An error callback for failed or no matched requests - * - * @return Hook - */ - public static function error(): Hook - { - $hook = new Hook(); - $hook->groups(['*']); - - self::$errors[] = $hook; - - return $hook; - } - /** * Get Mode * @@ -314,24 +202,6 @@ public static function setMode(string $value): void self::$mode = $value; } - /** - * Get Container - * - * @return Container - */ - public function getContainer(): Container - { - return $this->container; - } - - /** - * Set Container - */ - public function setContainer(Container $container): void - { - $this->container = $container; - } - /** * Get allow override * @@ -355,36 +225,6 @@ public static function setAllowOverride(bool $value): void Router::setAllowOverride($value); } - /** - * Is http in production mode? - * - * @return bool - */ - public static function isProduction(): bool - { - return self::MODE_TYPE_PRODUCTION === self::$mode; - } - - /** - * Is http in development mode? - * - * @return bool - */ - public static function isDevelopment(): bool - { - return self::MODE_TYPE_DEVELOPMENT === self::$mode; - } - - /** - * Is http in stage mode? - * - * @return bool - */ - public static function isStage(): bool - { - return self::MODE_TYPE_STAGE === self::$mode; - } - /** * Add Route * @@ -454,13 +294,6 @@ protected function getFileMimeType(string $uri): mixed return $this->files->getFileMimeType($uri); } - public static function onStart(): Hook - { - $hook = new Hook(); - self::$startHooks[] = $hook; - return $hook; - } - public function start() { $this->server->onRequest(function ($request, $response) { @@ -505,7 +338,7 @@ public function start() ; try { - foreach (self::$startHooks as $hook) { + foreach (self::$start as $hook) { $this->prepare($container, $hook, [], [])->inject($hook, true); } } catch(\Exception $e) { @@ -632,53 +465,6 @@ protected function lifecycle(Route $route, Request $request, Container $context) return $this; } - /** - * Prepare hook for injection, add dependencies, run validation. - * - * @param Hook $hook - * @param array $values - * @param array $requestParams - * @return Container - * - * @throws Exception - */ - protected function prepare(Container $context, Hook $hook, array $values = [], array $requestParams = []): Container - { - foreach ($hook->getParams() as $key => $param) { // Get value from route or request object - $existsInRequest = \array_key_exists($key, $requestParams); - $existsInValues = \array_key_exists($key, $values); - $paramExists = $existsInRequest || $existsInValues; - $arg = $existsInRequest ? $requestParams[$key] : $param['default']; - - $value = $existsInValues ? $values[$key] : $arg; - - /** - * Validation - */ - if (!$param['skipValidation']) { - if (!$paramExists && !$param['optional']) { - throw new Exception('Param "' . $key . '" is not optional.', 400); - } - - if ($paramExists) { - $this->validate($key, $param, $value, $context); - } - } - - $hook->setParamValue($key, $value); - - $dependencyForValue = new Dependency(); - $dependencyForValue - ->setName($key) - ->setCallback(fn () => $value) - ; - - $context->set($dependencyForValue); - } - - return $context; - } - /** * Run * @@ -813,50 +599,6 @@ public function run(Container $context): static return $this; } - /** - * Validate Param - * - * Creates an validator instance and validate given value with given rules. - * - * @param string $key - * @param array $param - * @param mixed $value - * @return void - * - * @throws Exception - */ - protected function validate(string $key, array $param, mixed $value, Container $context): void - { - if ($param['optional'] && \is_null($value)) { - return; - } - - $validator = $param['validator']; // checking whether the class exists - - if (\is_callable($validator)) { - - $dependency = new Dependency(); - $dependency - ->setName('_validator:'.$key) - ->setCallback($param['validator']) - ; - - foreach ($param['injections'] as $injection) { - $dependency->inject($injection); - } - - $validator = $context->inject($dependency); - } - - if (!$validator instanceof Validator) { // is the validator object an instance of the Validator class - throw new Exception('Validator object is not an instance of the Validator class', 500); - } - - if (!$validator->isValid($value)) { - throw new Exception('Invalid `' . $key . '` param: ' . $validator->getDescription(), 400); - } - } - /** * Reset all the static variables * @@ -865,11 +607,7 @@ protected function validate(string $key, array $param, mixed $value, Container $ public static function reset(): void { Router::reset(); - self::$mode = ''; - self::$errors = []; - self::$init = []; - self::$shutdown = []; self::$options = []; - self::$startHooks = []; + parent::reset(); } } diff --git a/src/Http/Validator.php b/src/Http/Validator.php index 6a8304ea..0026fc6e 100755 --- a/src/Http/Validator.php +++ b/src/Http/Validator.php @@ -2,56 +2,9 @@ namespace Utopia\Http; -abstract class Validator -{ - public const TYPE_BOOLEAN = 'boolean'; - - public const TYPE_INTEGER = 'integer'; - - public const TYPE_FLOAT = 'double'; /* gettype() returns 'double' for historical reasons */ - - public const TYPE_STRING = 'string'; - - public const TYPE_ARRAY = 'array'; - - public const TYPE_OBJECT = 'object'; +use Utopia\Servers\Validator as ServersValidator; - public const TYPE_MIXED = 'mixed'; - - /** - * Get Description - * - * Returns validator description - * - * @return string - */ - abstract public function getDescription(): string; - - /** - * Is array - * - * Returns true if an array or false if not. - * - * @return bool - */ - abstract public function isArray(): bool; - - /** - * Is valid - * - * Returns true if valid or false if not. - * - * @param mixed $value - * @return bool - */ - abstract public function isValid($value): bool; - - /** - * Get Type - * - * Returns validator type. - * - * @return string - */ - abstract public function getType(): string; +abstract class Validator extends ServersValidator +{ + } From 488706fcb11c7725aecf5764df9198d1389e455b Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:27:32 +0200 Subject: [PATCH 38/71] Update TESTING argument in Dockerfile.swoole --- Dockerfile.swoole | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.swoole b/Dockerfile.swoole index f2267a55..a930c97a 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -1,6 +1,6 @@ FROM composer:2.0 AS step0 -ARG TESTING=false +ARG TESTING=true ARG DEBUG=false ENV TESTING=$TESTING @@ -16,7 +16,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ FROM appwrite/base:0.9.0 as final -ARG TESTING=false +ARG TESTING=true ARG DEBUG=false ENV TESTING=$TESTING From 06a134c5eaf6730e557515e6e8a3e11d8fee0378 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:41:01 +0200 Subject: [PATCH 39/71] Updated deps --- composer.lock | 106 ++------------------------------------------------ 1 file changed, 4 insertions(+), 102 deletions(-) diff --git a/composer.lock b/composer.lock index 46f4edf6..2318987c 100644 --- a/composer.lock +++ b/composer.lock @@ -6,55 +6,6 @@ ], "content-hash": "f961290f450cd8657302383ece07a86b", "packages": [ - { - "name": "utopia-php/cli", - "version": "0.17.0", - "source": { - "type": "git", - "url": "https://github.com/utopia-php/cli.git", - "reference": "0829fd5215afe88f53f3091cedc808da801fd1bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cli/zipball/0829fd5215afe88f53f3091cedc808da801fd1bb", - "reference": "0829fd5215afe88f53f3091cedc808da801fd1bb", - "shasum": "" - }, - "require": { - "php": ">=7.4", - "utopia-php/framework": "0.34.*" - }, - "require-dev": { - "laravel/pint": "1.2.*", - "phpunit/phpunit": "^9.3", - "squizlabs/php_codesniffer": "^3.6", - "vimeo/psalm": "4.0.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Utopia\\CLI\\": "src/CLI" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A simple CLI library to manage command line applications", - "keywords": [ - "cli", - "command line", - "framework", - "php", - "upf", - "utopia" - ], - "support": { - "issues": "https://github.com/utopia-php/cli/issues", - "source": "https://github.com/utopia-php/cli/tree/0.17.0" - }, - "time": "2024-01-24T11:37:29+00:00" - }, { "name": "utopia-php/di", "version": "dev-main", @@ -117,71 +68,22 @@ }, "time": "2024-04-18T20:06:02+00:00" }, - { - "name": "utopia-php/framework", - "version": "0.34.2", - "source": { - "type": "git", - "url": "https://github.com/utopia-php/http.git", - "reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/fd126c02b78cc80678c9638f7b335dfb4a841b78", - "reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78", - "shasum": "" - }, - "require": { - "ext-swoole": "*", - "php": ">=8.0" - }, - "require-dev": { - "laravel/pint": "^1.2", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.5.25", - "swoole/ide-helper": "4.8.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Utopia\\Http\\": "src/Http" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A simple, light and advanced PHP HTTP framework", - "keywords": [ - "framework", - "http", - "php", - "upf" - ], - "support": { - "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.34.2" - }, - "time": "2024-02-20T11:36:56+00:00" - }, { "name": "utopia-php/servers", "version": "dev-dev", "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "afde8000e4d87ab1bb3cceba1c17e2506292123a" + "reference": "253ae7c51be0f0ade4e8ffb3e8c142cc27819374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/afde8000e4d87ab1bb3cceba1c17e2506292123a", - "reference": "afde8000e4d87ab1bb3cceba1c17e2506292123a", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/253ae7c51be0f0ade4e8ffb3e8c142cc27819374", + "reference": "253ae7c51be0f0ade4e8ffb3e8c142cc27819374", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/cli": "0.17.*", "utopia-php/di": "dev-main" }, "require-dev": { @@ -235,7 +137,7 @@ "source": "https://github.com/utopia-php/servers/tree/dev", "issues": "https://github.com/utopia-php/servers/issues" }, - "time": "2024-04-18T20:05:13+00:00" + "time": "2024-04-18T20:40:06+00:00" } ], "packages-dev": [ From 1c1b5a337d2529dde40079c57e8849e7d473dfd0 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:43:19 +0200 Subject: [PATCH 40/71] Fixed format --- src/Http/Adapter/Swoole/Server.php | 2 -- src/Http/Validator.php | 1 - tests/e2e/BaseTest.php | 2 +- tests/e2e/init.php | 2 +- tests/e2e/server-swoole.php | 5 ++--- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 4cdc93b2..0724430f 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -6,8 +6,6 @@ use Swoole\Http\Server as SwooleServer; use Swoole\Runtime; -use function Swoole\Coroutine\run; - class Server extends Adapter { protected SwooleServer $server; diff --git a/src/Http/Validator.php b/src/Http/Validator.php index 0026fc6e..551d1cea 100755 --- a/src/Http/Validator.php +++ b/src/Http/Validator.php @@ -6,5 +6,4 @@ abstract class Validator extends ServersValidator { - } diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index e04c4016..f7be2237 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -73,7 +73,7 @@ public function testParamInjection() $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringStartsWith('Hello World!test4573', $response['body']); } - + public function testNotFound() { $response = $this->client->call(Client::METHOD_GET, '/non-existing-page'); diff --git a/tests/e2e/init.php b/tests/e2e/init.php index f5e736dd..540891e6 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -119,7 +119,7 @@ Http::get('/param-injection') ->inject('response') - ->param('param', 'default', fn($num) => new Text($num), 'test param', false, ['num']) + ->param('param', 'default', fn ($num) => new Text($num), 'test param', false, ['num']) ->action(function (Response $response, string $param) { $response->send('Hello World!' . $param); }); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 2f3d1eda..367d4ee7 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -14,15 +14,14 @@ require_once __DIR__.'/init.php'; -$pool = new PDOPool((new PDOConfig) +$pool = new PDOPool((new PDOConfig()) ->withHost('mariadb') ->withPort(3306) // ->withUnixSocket('/tmp/mysql.sock') ->withDbName('test') ->withCharset('utf8mb4') ->withUsername('user') - ->withPassword('password') -, 9000); + ->withPassword('password'), 9000); $dependency = new Dependency(); From 6e9715f890694308546bf154ed91e91a7ec7d16e Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:44:37 +0200 Subject: [PATCH 41/71] Fixed format tests --- Dockerfile.swoole | 4 ++-- src/Http/Adapter/Swoole/Server.php | 2 -- tests/e2e/BaseTest.php | 2 +- tests/e2e/init.php | 2 +- tests/e2e/server-swoole.php | 5 ++--- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Dockerfile.swoole b/Dockerfile.swoole index f2267a55..a930c97a 100644 --- a/Dockerfile.swoole +++ b/Dockerfile.swoole @@ -1,6 +1,6 @@ FROM composer:2.0 AS step0 -ARG TESTING=false +ARG TESTING=true ARG DEBUG=false ENV TESTING=$TESTING @@ -16,7 +16,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ FROM appwrite/base:0.9.0 as final -ARG TESTING=false +ARG TESTING=true ARG DEBUG=false ENV TESTING=$TESTING diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 4cdc93b2..0724430f 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -6,8 +6,6 @@ use Swoole\Http\Server as SwooleServer; use Swoole\Runtime; -use function Swoole\Coroutine\run; - class Server extends Adapter { protected SwooleServer $server; diff --git a/tests/e2e/BaseTest.php b/tests/e2e/BaseTest.php index e04c4016..f7be2237 100644 --- a/tests/e2e/BaseTest.php +++ b/tests/e2e/BaseTest.php @@ -73,7 +73,7 @@ public function testParamInjection() $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringStartsWith('Hello World!test4573', $response['body']); } - + public function testNotFound() { $response = $this->client->call(Client::METHOD_GET, '/non-existing-page'); diff --git a/tests/e2e/init.php b/tests/e2e/init.php index f5e736dd..540891e6 100644 --- a/tests/e2e/init.php +++ b/tests/e2e/init.php @@ -119,7 +119,7 @@ Http::get('/param-injection') ->inject('response') - ->param('param', 'default', fn($num) => new Text($num), 'test param', false, ['num']) + ->param('param', 'default', fn ($num) => new Text($num), 'test param', false, ['num']) ->action(function (Response $response, string $param) { $response->send('Hello World!' . $param); }); diff --git a/tests/e2e/server-swoole.php b/tests/e2e/server-swoole.php index 2f3d1eda..367d4ee7 100755 --- a/tests/e2e/server-swoole.php +++ b/tests/e2e/server-swoole.php @@ -14,15 +14,14 @@ require_once __DIR__.'/init.php'; -$pool = new PDOPool((new PDOConfig) +$pool = new PDOPool((new PDOConfig()) ->withHost('mariadb') ->withPort(3306) // ->withUnixSocket('/tmp/mysql.sock') ->withDbName('test') ->withCharset('utf8mb4') ->withUsername('user') - ->withPassword('password') -, 9000); + ->withPassword('password'), 9000); $dependency = new Dependency(); From 62c2b5b2b1e0e598cd67d79143e4dd210c44d499 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 22:53:06 +0200 Subject: [PATCH 42/71] Fixed autolaoding --- composer.lock | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index fe3851f1..c9a95fa5 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679" + "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/0bb7af5693bc131f4d2ce34d3f732d41e6637679", - "reference": "0bb7af5693bc131f4d2ce34d3f732d41e6637679", + "url": "https://api.github.com/repos/utopia-php/di/zipball/fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", + "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-08T22:41:41+00:00" + "time": "2024-04-18T20:06:02+00:00" } ], "packages-dev": [ @@ -796,16 +796,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.66", + "version": "1.10.67", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd" + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", "shasum": "" }, "require": { @@ -848,13 +848,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-28T16:17:31+00:00" + "time": "2024-04-16T07:22:02+00:00" }, { "name": "phpunit/php-code-coverage", From e84ceaeda253c5b942972450dec73b91405c1cf7 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Thu, 18 Apr 2024 23:04:25 +0200 Subject: [PATCH 43/71] Fixed inheritance --- composer.lock | 10 +++++----- src/Http/Validator.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 2318987c..ef084367 100644 --- a/composer.lock +++ b/composer.lock @@ -74,12 +74,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "253ae7c51be0f0ade4e8ffb3e8c142cc27819374" + "reference": "43881ed83f97cb31af7f940db74c520c70b914ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/253ae7c51be0f0ade4e8ffb3e8c142cc27819374", - "reference": "253ae7c51be0f0ade4e8ffb3e8c142cc27819374", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/43881ed83f97cb31af7f940db74c520c70b914ab", + "reference": "43881ed83f97cb31af7f940db74c520c70b914ab", "shasum": "" }, "require": { @@ -94,7 +94,7 @@ "type": "library", "autoload": { "psr-4": { - "Utopia\\Queue\\": "src/Servers" + "Utopia\\Servers\\": "src/Servers" } }, "autoload-dev": { @@ -137,7 +137,7 @@ "source": "https://github.com/utopia-php/servers/tree/dev", "issues": "https://github.com/utopia-php/servers/issues" }, - "time": "2024-04-18T20:40:06+00:00" + "time": "2024-04-18T20:51:43+00:00" } ], "packages-dev": [ diff --git a/src/Http/Validator.php b/src/Http/Validator.php index 551d1cea..f75b1550 100755 --- a/src/Http/Validator.php +++ b/src/Http/Validator.php @@ -6,4 +6,17 @@ abstract class Validator extends ServersValidator { + public const TYPE_BOOLEAN = 'boolean'; + + public const TYPE_INTEGER = 'integer'; + + public const TYPE_FLOAT = 'double'; /* gettype() returns 'double' for historical reasons */ + + public const TYPE_STRING = 'string'; + + public const TYPE_ARRAY = 'array'; + + public const TYPE_OBJECT = 'object'; + + public const TYPE_MIXED = 'mixed'; } From 4c4e85eac5164eabc97bc57708310b3e6419b9d6 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 15:38:46 +0200 Subject: [PATCH 44/71] Added methods for get and set query strings --- src/Http/Adapter/FPM/Request.php | 27 ++++++++++++++++ src/Http/Adapter/Swoole/Request.php | 27 ++++++++++++++++ src/Http/Request.php | 49 +++++++++++++++++++---------- tests/RequestTest.php | 20 ++++++++++-- 4 files changed, 105 insertions(+), 18 deletions(-) diff --git a/src/Http/Adapter/FPM/Request.php b/src/Http/Adapter/FPM/Request.php index ecabb457..5de5d6d7 100644 --- a/src/Http/Adapter/FPM/Request.php +++ b/src/Http/Adapter/FPM/Request.php @@ -164,6 +164,33 @@ public function setURI(string $uri): static return $this; } + + /** + * Get Query String + * + * Return HTTP request query string + * + * @return string + */ + public function getQueryString(): string + { + return $this->getServer('QUERY_STRING') ?? ''; + } + + /** + * Set Query String + * + * Set HTTP request query string + * + * @param string $uri + * @return static + */ + public function setQueryString(string $value): static + { + $this->setServer('QUERY_STRING', $value); + + return $this; + } /** * Get files diff --git a/src/Http/Adapter/Swoole/Request.php b/src/Http/Adapter/Swoole/Request.php index 9e0ffa11..96ab81a5 100644 --- a/src/Http/Adapter/Swoole/Request.php +++ b/src/Http/Adapter/Swoole/Request.php @@ -179,6 +179,33 @@ public function setURI(string $uri): static return $this; } + /** + * Get Query String + * + * Return HTTP request query string + * + * @return string + */ + public function getQueryString(): string + { + return $this->getServer('query_string') ?? ''; + } + + /** + * Set Query String + * + * Set HTTP request query string + * + * @param string $uri + * @return static + */ + public function setQueryString(string $value): static + { + $this->setServer('query_string', $value); + + return $this; + } + /** * Get Referer * diff --git a/src/Http/Request.php b/src/Http/Request.php index 65f67b28..8eefde7a 100755 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -90,6 +90,19 @@ public function getQuery(string $key, mixed $default = null): mixed return $this->queryString[$key] ?? $default; } + /** + * Set query string parameters + * + * @param array $params + * @return static + */ + public function setQuery(array $params): static + { + $this->queryString = $params; + + return $this; + } + /** * Get payload * @@ -203,10 +216,7 @@ abstract public function setMethod(string $method): static; * * @return string */ - public function getURI(): string - { - return $this->getServer('REQUEST_URI') ?? ''; - } + abstract public function getURI(): string; /** * Get Path @@ -218,6 +228,25 @@ public function getURI(): string */ abstract public function setURI(string $uri): static; + /** + * Get query string + * + * Method for querying HTTP GET request query string + * + * @return string + */ + abstract public function getQueryString(): string; + + /** + * Set query string + * + * Method for setting HTTP GET request query string + * + * @param string $value + * @return string + */ + abstract public function setQueryString(string $value): static; + /** * Get files * @@ -454,18 +483,6 @@ public function getRangeUnit(): ?string return null; } - /** - * Set query string parameters - * - * @param array $params - * @return static - */ - public function setQueryString(array $params): static - { - $this->queryString = $params; - - return $this; - } /** * Set payload parameters diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 55d49ee9..6138ae78 100755 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -65,9 +65,9 @@ public function testCanGetQueryParameter() $this->assertEquals($this->request->getQuery('unknown', 'test'), 'test'); } - public function testCanSetQueryString() + public function testCanSetQuery() { - $this->request->setQueryString(['key' => 'value']); + $this->request->setQuery(['key' => 'value']); $this->assertEquals($this->request->getQuery('key'), 'value'); $this->assertEquals($this->request->getQuery('unknown', 'test'), 'test'); @@ -156,6 +156,22 @@ public function testCanSetUri() $this->assertEquals('/page.html', $this->request->getURI()); } + public function testCanGetQueryString() + { + $this->assertEquals('', $this->request->getQueryString()); + + $_SERVER['QUERY_STRING'] = 'text=hello&value=key'; + + $this->assertEquals('text=hello&value=key', $this->request->getQueryString()); + } + + public function testCanSetQueryString() + { + $this->request->setURI('text=hello&value=key'); + + $this->assertEquals('text=hello&value=key', $this->request->getURI()); + } + public function testCanGetPort() { $_SERVER['HTTP_HOST'] = 'localhost:8080'; From 395f876b4f87d428ebdf85a7308376eba4c8019f Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 15:51:18 +0200 Subject: [PATCH 45/71] Updated composer --- composer.lock | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/composer.lock b/composer.lock index ef084367..6ced2394 100644 --- a/composer.lock +++ b/composer.lock @@ -74,12 +74,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "43881ed83f97cb31af7f940db74c520c70b914ab" + "reference": "20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/43881ed83f97cb31af7f940db74c520c70b914ab", - "reference": "43881ed83f97cb31af7f940db74c520c70b914ab", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd", + "reference": "20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd", "shasum": "" }, "require": { @@ -137,7 +137,7 @@ "source": "https://github.com/utopia-php/servers/tree/dev", "issues": "https://github.com/utopia-php/servers/issues" }, - "time": "2024-04-18T20:51:43+00:00" + "time": "2024-04-21T18:53:43+00:00" } ], "packages-dev": [ @@ -499,12 +499,12 @@ "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe" + "reference": "c5ee33df86c06b3278c670f64273b1ba768a0744" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/46be4560c4cd4bab2b74882c0da39a4548a5cfbe", - "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c5ee33df86c06b3278c670f64273b1ba768a0744", + "reference": "c5ee33df86c06b3278c670f64273b1ba768a0744", "shasum": "" }, "require": { @@ -550,7 +550,7 @@ "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/master" }, - "time": "2024-03-17T10:24:36+00:00" + "time": "2024-04-19T12:04:10+00:00" }, { "name": "phar-io/manifest", @@ -884,12 +884,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5" + "reference": "3b03bac1068a585926a14e97692baef8642c2a1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5", - "reference": "1ab6c28b7f4c273d1ffd6a4a5d8ef7e989ea04c5", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3b03bac1068a585926a14e97692baef8642c2a1b", + "reference": "3b03bac1068a585926a14e97692baef8642c2a1b", "shasum": "" }, "require": { @@ -935,7 +935,7 @@ "type": "github" } ], - "time": "2024-04-18T15:41:16+00:00" + "time": "2024-04-22T13:39:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1262,12 +1262,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2f5cc6727bef6304e013d24e16e2203ca1f5ea94" + "reference": "33a0610878994fc134c74c25d5276d606d49079b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f5cc6727bef6304e013d24e16e2203ca1f5ea94", - "reference": "2f5cc6727bef6304e013d24e16e2203ca1f5ea94", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33a0610878994fc134c74c25d5276d606d49079b", + "reference": "33a0610878994fc134c74c25d5276d606d49079b", "shasum": "" }, "require": { @@ -1357,7 +1357,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T12:34:34+00:00" + "time": "2024-04-20T06:05:08+00:00" }, { "name": "psr/cache", @@ -2949,12 +2949,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe", + "reference": "c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe", "shasum": "" }, "require": { @@ -3005,7 +3005,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/1.x" }, "funding": [ { @@ -3021,7 +3021,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-04-19T06:31:17+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -3029,12 +3029,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "0a1df740cbb01859ce1bac85b0ad58ffe02f69b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/0a1df740cbb01859ce1bac85b0ad58ffe02f69b6", + "reference": "0a1df740cbb01859ce1bac85b0ad58ffe02f69b6", "shasum": "" }, "require": { @@ -3084,7 +3084,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/1.x" }, "funding": [ { @@ -3100,7 +3100,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-04-19T06:31:17+00:00" }, { "name": "symfony/polyfill-intl-normalizer", @@ -3108,12 +3108,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "2a090dc3db090fcb35cc7329d18a07f281f15d79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2a090dc3db090fcb35cc7329d18a07f281f15d79", + "reference": "2a090dc3db090fcb35cc7329d18a07f281f15d79", "shasum": "" }, "require": { @@ -3166,7 +3166,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/1.x" }, "funding": [ { @@ -3182,7 +3182,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-04-19T06:31:17+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3190,12 +3190,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3cf95983a25d6439cac5f5164f0bfeeb1eb5d264" + "reference": "e642fbe7a7b73cdb05460555289a9057bfd6ead6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3cf95983a25d6439cac5f5164f0bfeeb1eb5d264", - "reference": "3cf95983a25d6439cac5f5164f0bfeeb1eb5d264", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e642fbe7a7b73cdb05460555289a9057bfd6ead6", + "reference": "e642fbe7a7b73cdb05460555289a9057bfd6ead6", "shasum": "" }, "require": { @@ -3263,7 +3263,7 @@ "type": "tidelift" } ], - "time": "2024-04-12T09:26:28+00:00" + "time": "2024-04-19T06:31:17+00:00" }, { "name": "symfony/process", From b45169405bd28db2acdcecf0010a09e217897649 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 16:00:27 +0200 Subject: [PATCH 46/71] Fixed format --- src/Http/Adapter/FPM/Request.php | 2 +- src/Http/Request.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Adapter/FPM/Request.php b/src/Http/Adapter/FPM/Request.php index 5de5d6d7..1cad6db1 100644 --- a/src/Http/Adapter/FPM/Request.php +++ b/src/Http/Adapter/FPM/Request.php @@ -164,7 +164,7 @@ public function setURI(string $uri): static return $this; } - + /** * Get Query String * diff --git a/src/Http/Request.php b/src/Http/Request.php index 8eefde7a..66d09a78 100755 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -236,12 +236,12 @@ abstract public function setURI(string $uri): static; * @return string */ abstract public function getQueryString(): string; - + /** * Set query string * * Method for setting HTTP GET request query string - * + * * @param string $value * @return string */ From b7494aa6454fbe290fb2ab9f50fd5b187138788d Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 16:06:34 +0200 Subject: [PATCH 47/71] Fixed codeQL --- src/Http/Adapter/FPM/Request.php | 2 +- src/Http/Adapter/Swoole/Request.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Adapter/FPM/Request.php b/src/Http/Adapter/FPM/Request.php index 1cad6db1..bdc8ebf5 100644 --- a/src/Http/Adapter/FPM/Request.php +++ b/src/Http/Adapter/FPM/Request.php @@ -182,7 +182,7 @@ public function getQueryString(): string * * Set HTTP request query string * - * @param string $uri + * @param string $value * @return static */ public function setQueryString(string $value): static diff --git a/src/Http/Adapter/Swoole/Request.php b/src/Http/Adapter/Swoole/Request.php index 96ab81a5..d93310d2 100644 --- a/src/Http/Adapter/Swoole/Request.php +++ b/src/Http/Adapter/Swoole/Request.php @@ -196,7 +196,7 @@ public function getQueryString(): string * * Set HTTP request query string * - * @param string $uri + * @param string $value * @return static */ public function setQueryString(string $value): static From f16451f6e5d2f0fe737ec46d3fb939934a2b25e0 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 16:31:22 +0200 Subject: [PATCH 48/71] Fixed response type --- src/Http/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Request.php b/src/Http/Request.php index 66d09a78..e8894e04 100755 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -243,7 +243,7 @@ abstract public function getQueryString(): string; * Method for setting HTTP GET request query string * * @param string $value - * @return string + * @return static */ abstract public function setQueryString(string $value): static; From 7147637c9ac78de0703365ad7098428049e3457d Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 21:51:35 +0200 Subject: [PATCH 49/71] Fixed error injection --- src/Http/Http.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 00569b20..4b95f4b8 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -534,7 +534,7 @@ public function run(Container $context): static /** @var Hook $error */ if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $this->container->set( + $$context->set( $dependency ->setName('error') ->setCallback(fn () => $e) @@ -570,7 +570,7 @@ public function run(Container $context): static foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $this->container->set( + $context->set( $dependency ->setName('error') ->setCallback(fn () => $e) From aa9bec501aaf573be665485ed48ce67ba0b32668 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 22:02:03 +0200 Subject: [PATCH 50/71] Fixed typo --- src/Http/Http.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 4b95f4b8..46843fd7 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -534,7 +534,7 @@ public function run(Container $context): static /** @var Hook $error */ if (in_array('*', $error->getGroups())) { $dependency = new Dependency(); - $$context->set( + $context->set( $dependency ->setName('error') ->setCallback(fn () => $e) From db782cedc80a639d1608d6dca7771fcff4031d88 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 22:19:36 +0200 Subject: [PATCH 51/71] Updated server header logic --- src/Http/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index ea5aa9e0..66a0eeaa 100755 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -476,7 +476,7 @@ public function send(string $body = ''): void $this->sent = true; $this - ->addHeader('Server', 'Utopia/Http') + ->addHeader('Server', array_key_exists('Server', $this->headers) ? $this->headers['Server'] : 'Utopia/Http') ->addHeader('X-Debug-Speed', (string) (\microtime(true) - $this->startTime)) ; From cc3341f13d6b90f3104f197acb9136abe2fc708a Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Mon, 22 Apr 2024 23:25:06 +0200 Subject: [PATCH 52/71] Updated composer --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 6ced2394..265089bc 100644 --- a/composer.lock +++ b/composer.lock @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2" + "reference": "a0c8be65c19570c80e904d58f54bdd901d1d5d9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", - "reference": "fb3c45b268018b87dcbbf87ad943ced9eea3bbe2", + "url": "https://api.github.com/repos/utopia-php/di/zipball/a0c8be65c19570c80e904d58f54bdd901d1d5d9c", + "reference": "a0c8be65c19570c80e904d58f54bdd901d1d5d9c", "shasum": "" }, "require": { @@ -66,7 +66,7 @@ "source": "https://github.com/utopia-php/di/tree/main", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-18T20:06:02+00:00" + "time": "2024-04-22T21:22:44+00:00" }, { "name": "utopia-php/servers", @@ -74,12 +74,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd" + "reference": "e7eee7f82399c89adc28cf79912a9a41d7bb3233" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd", - "reference": "20bb7ab93c21d0ae37bc309d41b70ddf2a78a6fd", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/e7eee7f82399c89adc28cf79912a9a41d7bb3233", + "reference": "e7eee7f82399c89adc28cf79912a9a41d7bb3233", "shasum": "" }, "require": { @@ -137,7 +137,7 @@ "source": "https://github.com/utopia-php/servers/tree/dev", "issues": "https://github.com/utopia-php/servers/issues" }, - "time": "2024-04-21T18:53:43+00:00" + "time": "2024-04-22T21:23:28+00:00" } ], "packages-dev": [ From d64cfc3868057d539c7fa27c672ac938eedc3656 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Mon, 10 Jun 2024 08:37:51 -0400 Subject: [PATCH 53/71] feat: adding `getRoutes` function --- src/Http/Router.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Http/Router.php b/src/Http/Router.php index 90c0fcf2..d3324553 100644 --- a/src/Http/Router.php +++ b/src/Http/Router.php @@ -32,6 +32,16 @@ class Router */ protected static array $params = []; + /** + * Get all registered routes. + * + * @return array + */ + public static function getRoutes(): array + { + return self::$routes; + } + /** * Get allow override * From f54000a0f47b6eea34a373212711729b336a56bc Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:03:46 -0400 Subject: [PATCH 54/71] feat: adding context and http --- src/Http/Http.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Http/Http.php b/src/Http/Http.php index 46843fd7..ebc39e93 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -297,7 +297,6 @@ protected function getFileMimeType(string $uri): mixed public function start() { $this->server->onRequest(function ($request, $response) { - $context = clone $this->container; $dependency = new Dependency(); if(!\is_null($this->requestClass)) { @@ -320,6 +319,16 @@ public function start() ->setName('response') ->setCallback(fn () => $response) ) + ->set( + clone $dependency + ->setName('http') + ->setCallback(fn () => $this) + ) + ->set( + clone $dependency + ->setName('context') + ->setCallback(fn () => $context) + ) ; $this->run($context); From 8eda2d0fd0cacb0ea5c7bad4e3daf17abbb89770 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:33:52 -0400 Subject: [PATCH 55/71] feat: adding list of routes --- src/Http/Http.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Http/Http.php b/src/Http/Http.php index ebc39e93..5e25b864 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -202,6 +202,18 @@ public static function setMode(string $value): void self::$mode = $value; } + /** + * Get Routes + * + * Get all application routes + * + * @return array + */ + public static function getRoutes(): array + { + return Router::getRoutes(); + } + /** * Get allow override * From bf2474554f78d870c74aaaa1dfb4f54795ae9497 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:38:45 -0400 Subject: [PATCH 56/71] feat: adding external execute for GraphQL --- src/Http/Http.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Http/Http.php b/src/Http/Http.php index 5e25b864..e2726c82 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -404,6 +404,12 @@ public function match(Request $request): ?Route return Router::match($method, $url); } + + public function execute(Route $route, Request $request, Container $context): self + { + return $this->lifecycle($route, $request, $context); + } + /** * Execute a given route with middlewares and error handling * From 65d4fb863f215b89fdaa269ef6cc2951b52663af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 06:28:28 +0000 Subject: [PATCH 57/71] Implement rules for multiple validator --- composer.lock | 292 ++++++++++++++++--------------- src/Http/Validator/Multiple.php | 54 ++++-- tests/Validator/MultipleTest.php | 26 +++ 3 files changed, 214 insertions(+), 158 deletions(-) diff --git a/composer.lock b/composer.lock index cb7278bc..67cde3f0 100644 --- a/composer.lock +++ b/composer.lock @@ -232,16 +232,16 @@ }, { "name": "laravel/pint", - "version": "v1.14.0", + "version": "v1.16.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "6b127276e3f263f7bb17d5077e9e0269e61b2a0e" + "reference": "9266a47f1b9231b83e0cfd849009547329d871b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/6b127276e3f263f7bb17d5077e9e0269e61b2a0e", - "reference": "6b127276e3f263f7bb17d5077e9e0269e61b2a0e", + "url": "https://api.github.com/repos/laravel/pint/zipball/9266a47f1b9231b83e0cfd849009547329d871b1", + "reference": "9266a47f1b9231b83e0cfd849009547329d871b1", "shasum": "" }, "require": { @@ -252,13 +252,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.49.0", - "illuminate/view": "^10.43.0", - "larastan/larastan": "^2.8.1", - "laravel-zero/framework": "^10.3.0", - "mockery/mockery": "^1.6.7", + "friendsofphp/php-cs-fixer": "^3.59.3", + "illuminate/view": "^10.48.12", + "larastan/larastan": "^2.9.7", + "laravel-zero/framework": "^10.4.0", + "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.33.6" + "pestphp/pest": "^2.34.8" }, "bin": [ "builds/pint" @@ -294,20 +294,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-02-20T17:38:05+00:00" + "time": "2024-06-18T16:50:05+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -315,11 +315,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -345,7 +346,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -353,20 +354,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -377,7 +378,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -409,9 +410,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", @@ -635,16 +636,16 @@ }, { "name": "phpbench/phpbench", - "version": "1.2.15", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c" + "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/f7000319695cfad04a57fc64bf7ef7abdf4c437c", - "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", + "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", "shasum": "" }, "require": { @@ -656,29 +657,30 @@ "ext-spl": "*", "ext-tokenizer": "*", "php": "^8.1", - "phpbench/container": "^2.1", + "phpbench/container": "^2.2", "phpbench/dom": "~0.3.3", "psr/log": "^1.1 || ^2.0 || ^3.0", "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0 || ^7.0", + "symfony/console": "^6.1 || ^7.0", + "symfony/filesystem": "^6.1 || ^7.0", + "symfony/finder": "^6.1 || ^7.0", + "symfony/options-resolver": "^6.1 || ^7.0", + "symfony/process": "^6.1 || ^7.0", "webmozart/glob": "^4.6" }, "require-dev": { "dantleech/invoke": "^2.0", + "ergebnis/composer-normalize": "^2.39", "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", "phpspec/prophecy": "dev-master", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.0", - "rector/rector": "^0.18.10", - "symfony/error-handler": "^5.2 || ^6.0 || ^7.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^10.4", + "rector/rector": "^0.18.11 || ^1.0.0", + "symfony/error-handler": "^6.1 || ^7.0", + "symfony/var-dumper": "^6.1 || ^7.0" }, "suggest": { "ext-xdebug": "For Xdebug profiling extension." @@ -721,7 +723,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.15" + "source": "https://github.com/phpbench/phpbench/tree/1.3.1" }, "funding": [ { @@ -729,20 +731,20 @@ "type": "github" } ], - "time": "2023-11-29T12:21:11+00:00" + "time": "2024-06-30T11:04:37+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.60", + "version": "1.11.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe" + "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6ac78f1165346c83b4a753f7e4186d969c6ad0ee", + "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee", "shasum": "" }, "require": { @@ -785,13 +787,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-07T13:30:19+00:00" + "time": "2024-07-01T15:33:06+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1114,16 +1112,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.17", + "version": "9.6.19", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", "shasum": "" }, "require": { @@ -1197,7 +1195,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" }, "funding": [ { @@ -1213,7 +1211,7 @@ "type": "tidelift" } ], - "time": "2024-02-23T13:14:51+00:00" + "time": "2024-04-05T04:35:58+00:00" }, { "name": "psr/cache", @@ -2169,16 +2167,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -2190,7 +2188,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2211,8 +2209,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -2220,7 +2217,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", @@ -2439,16 +2436,16 @@ }, { "name": "symfony/console", - "version": "v7.0.4", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" + "reference": "0aa29ca177f432ab68533432db0de059f39c92ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", + "url": "https://api.github.com/repos/symfony/console/zipball/0aa29ca177f432ab68533432db0de059f39c92ae", + "reference": "0aa29ca177f432ab68533432db0de059f39c92ae", "shasum": "" }, "require": { @@ -2512,7 +2509,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.4" + "source": "https://github.com/symfony/console/tree/v7.1.2" }, "funding": [ { @@ -2528,20 +2525,20 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-06-28T10:03:55+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -2550,7 +2547,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -2579,7 +2576,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -2595,20 +2592,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/filesystem", - "version": "v7.0.3", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12" + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12", - "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", "shasum": "" }, "require": { @@ -2616,6 +2613,9 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -2642,7 +2642,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.0.3" + "source": "https://github.com/symfony/filesystem/tree/v7.1.2" }, "funding": [ { @@ -2658,20 +2658,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-06-28T10:03:55+00:00" }, { "name": "symfony/finder", - "version": "v7.0.0", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "url": "https://api.github.com/repos/symfony/finder/zipball/fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6", "shasum": "" }, "require": { @@ -2706,7 +2706,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.0.0" + "source": "https://github.com/symfony/finder/tree/v7.1.1" }, "funding": [ { @@ -2722,20 +2722,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:59:56+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.0.0", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f" + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", "shasum": "" }, "require": { @@ -2773,7 +2773,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.0.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" }, "funding": [ { @@ -2789,20 +2789,20 @@ "type": "tidelift" } ], - "time": "2023-08-08T10:20:21+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -2852,7 +2852,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -2868,20 +2868,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -2930,7 +2930,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -2946,20 +2946,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -3011,7 +3011,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -3027,20 +3027,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -3091,7 +3091,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -3107,20 +3107,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/process", - "version": "v7.0.4", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9" + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9", + "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", "shasum": "" }, "require": { @@ -3152,7 +3152,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.0.4" + "source": "https://github.com/symfony/process/tree/v7.1.1" }, "funding": [ { @@ -3168,25 +3168,26 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -3194,7 +3195,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -3234,7 +3235,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -3250,20 +3251,20 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/string", - "version": "v7.0.4", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" + "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", + "url": "https://api.github.com/repos/symfony/string/zipball/14221089ac66cf82e3cf3d1c1da65de305587ff8", + "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8", "shasum": "" }, "require": { @@ -3277,6 +3278,7 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { + "symfony/emoji": "^7.1", "symfony/error-handler": "^6.4|^7.0", "symfony/http-client": "^6.4|^7.0", "symfony/intl": "^6.4|^7.0", @@ -3320,7 +3322,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.4" + "source": "https://github.com/symfony/string/tree/v7.1.2" }, "funding": [ { @@ -3336,7 +3338,7 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:17:36+00:00" + "time": "2024-06-28T09:27:18+00:00" }, { "name": "theseer/tokenizer", @@ -3390,16 +3392,16 @@ }, { "name": "webmozart/glob", - "version": "4.6.0", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655" + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655", - "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655", + "url": "https://api.github.com/repos/webmozarts/glob/zipball/8a2842112d6916e61e0e15e316465b611f3abc17", + "reference": "8a2842112d6916e61e0e15e316465b611f3abc17", "shasum": "" }, "require": { @@ -3433,9 +3435,9 @@ "description": "A PHP implementation of Ant's glob.", "support": { "issues": "https://github.com/webmozarts/glob/issues", - "source": "https://github.com/webmozarts/glob/tree/4.6.0" + "source": "https://github.com/webmozarts/glob/tree/4.7.0" }, - "time": "2022-05-24T19:45:58+00:00" + "time": "2024-03-07T20:33:40+00:00" } ], "aliases": [], diff --git a/src/Http/Validator/Multiple.php b/src/Http/Validator/Multiple.php index 4c919377..61b45d09 100644 --- a/src/Http/Validator/Multiple.php +++ b/src/Http/Validator/Multiple.php @@ -16,9 +16,14 @@ class Multiple extends Validator /** * @var Validator[] */ - protected $rules = []; + protected $validators = []; protected $type = self::TYPE_MIXED; + protected $rule = self::RULE_ALL; + + public const RULE_ALL = "ruleAll"; + public const RULE_ANY = "ruleAny"; + public const RULE_NONE = "ruleNone"; /** * Constructor @@ -29,26 +34,32 @@ class Multiple extends Validator * * $multiple = new Multiple([$validator1, $validator2]); * $multiple = new Multiple([$validator1, $validator2, $validator3], self::TYPE_STRING); + * + * Rule is set to define criteria of validation: + * RULE_ANY: At least one validator must pass + * RULE_ALL: All validators must pass + * RULE_NONE: No validators must pass - all validators must fail */ - public function __construct(array $rules, ?string $type = self::TYPE_MIXED) + public function __construct(array $validators, ?string $type = self::TYPE_MIXED, ?string $rule = self::RULE_ALL) { - foreach ($rules as $rule) { - $this->addRule($rule); + foreach ($validators as $validator) { + $this->addValidator($validator); } $this->type = $type; + $this->rule = $rule; } /** - * Add rule + * Add validator * - * Add a new rule to the end of the rules containing array + * Add a new validator to check against during isVaid() call * - * @param Validator $rule + * @param Validator $validator * @return $this */ - public function addRule(Validator $rule) + public function addValidator(Validator $validator) { - $this->rules[] = $rule; + $this->validators[] = $validator; return $this; } @@ -63,7 +74,7 @@ public function addRule(Validator $rule) public function getDescription(): string { $description = ''; - foreach ($this->rules as $key => $rule) { + foreach ($this->validators as $key => $rule) { $description .= ++$key . '. ' . $rule->getDescription() . " \n"; } @@ -80,12 +91,29 @@ public function getDescription(): string */ public function isValid(mixed $value): bool { - foreach ($this->rules as $rule) { /* @var $rule Validator */ - if (false === $rule->isValid($value)) { - return false; + foreach ($this->validators as $rule) { /* @var $rule Validator */ + $valid = $rule->isValid($value); + + // Oprimization improvements + if($this->rule === self::RULE_ALL) { + if(!$valid) { + return false; + } + } if($this->rule === self::RULE_NONE) { + if($valid) { + return false; + } + } if($this->rule === self::RULE_ANY) { + if($valid) { + return true; + } } } + if($this->rule === self::RULE_ANY) { + return false; + } + return true; } diff --git a/tests/Validator/MultipleTest.php b/tests/Validator/MultipleTest.php index 348c3244..9f1bf12d 100644 --- a/tests/Validator/MultipleTest.php +++ b/tests/Validator/MultipleTest.php @@ -32,4 +32,30 @@ public function testIsValid() $this->assertFalse($this->validator->isValid('example.com/hello-world')); $this->assertFalse($this->validator->isValid('')); } + + public function testRules() + { + $validTextValidUrl = 'http://example.com'; + $validTextInvalidUrl = 'hello world'; + $invalidTextValidUrl = 'http://example.com/very-long-url'; + $invalidTextInvalidUrl = 'Some very long text that is also not an URL'; + + $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_ALL); + $this->assertTrue($vaidator->isValid($validTextValidUrl)); + $this->assertFalse($vaidator->isValid($validTextInvalidUrl)); + $this->assertFalse($vaidator->isValid($invalidTextValidUrl)); + $this->assertFalse($vaidator->isValid($invalidTextInvalidUrl)); + + $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_ANY); + $this->assertTrue($vaidator->isValid($validTextValidUrl)); + $this->assertTrue($vaidator->isValid($validTextInvalidUrl)); + $this->assertTrue($vaidator->isValid($invalidTextValidUrl)); + $this->assertFalse($vaidator->isValid($invalidTextInvalidUrl)); + + $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_NONE); + $this->assertFalse($vaidator->isValid($validTextValidUrl)); + $this->assertFalse($vaidator->isValid($validTextInvalidUrl)); + $this->assertFalse($vaidator->isValid($invalidTextValidUrl)); + $this->assertTrue($vaidator->isValid($invalidTextInvalidUrl)); + } } From 102c44b46add9095ecaf8fd2945289bfbceffe75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 08:21:17 +0000 Subject: [PATCH 58/71] Separate validators --- src/Http/Validator/AllOf.php | 82 ++++++++++ src/Http/Validator/AnyOf.php | 82 ++++++++++ src/Http/Validator/Multiple.php | 143 ------------------ src/Http/Validator/NoneOf.php | 82 ++++++++++ .../{MultipleTest.php => MultipleOfTest.php} | 30 ++-- 5 files changed, 261 insertions(+), 158 deletions(-) create mode 100644 src/Http/Validator/AllOf.php create mode 100644 src/Http/Validator/AnyOf.php delete mode 100644 src/Http/Validator/Multiple.php create mode 100644 src/Http/Validator/NoneOf.php rename tests/Validator/{MultipleTest.php => MultipleOfTest.php} (60%) diff --git a/src/Http/Validator/AllOf.php b/src/Http/Validator/AllOf.php new file mode 100644 index 00000000..84cd8f9f --- /dev/null +++ b/src/Http/Validator/AllOf.php @@ -0,0 +1,82 @@ + $validators + */ + public function __construct(protected array $validators, protected string $type = self::TYPE_MIXED) + { + } + + /** + * Get Description + * + * Returns validator description + * + * @return string + */ + public function getDescription(): string + { + $description = ''; + foreach ($this->validators as $key => $rule) { + $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + } + + return $description; + } + + /** + * Is valid + * + * Validation will pass when all rules are valid if only one of the rules is invalid validation will fail. + * + * @param mixed $value + * @return bool + */ + public function isValid(mixed $value): bool + { + foreach ($this->validators as $rule) { + $valid = $rule->isValid($value); + + if(!$valid) { + return false; + } + } + + return true; + } + + /** + * Get Type + * + * Returns validator type. + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * Is array + * + * Function will return true if object is array. + * + * @return bool + */ + public function isArray(): bool + { + return true; + } +} diff --git a/src/Http/Validator/AnyOf.php b/src/Http/Validator/AnyOf.php new file mode 100644 index 00000000..253891dc --- /dev/null +++ b/src/Http/Validator/AnyOf.php @@ -0,0 +1,82 @@ + $validators + */ + public function __construct(protected array $validators, protected string $type = self::TYPE_MIXED) + { + } + + /** + * Get Description + * + * Returns validator description + * + * @return string + */ + public function getDescription(): string + { + $description = ''; + foreach ($this->validators as $key => $rule) { + $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + } + + return $description; + } + + /** + * Is valid + * + * Validation will pass when all rules are valid if only one of the rules is invalid validation will fail. + * + * @param mixed $value + * @return bool + */ + public function isValid(mixed $value): bool + { + foreach ($this->validators as $rule) { + $valid = $rule->isValid($value); + + if($valid) { + return true; + } + } + + return false; + } + + /** + * Get Type + * + * Returns validator type. + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * Is array + * + * Function will return true if object is array. + * + * @return bool + */ + public function isArray(): bool + { + return true; + } +} diff --git a/src/Http/Validator/Multiple.php b/src/Http/Validator/Multiple.php deleted file mode 100644 index 61b45d09..00000000 --- a/src/Http/Validator/Multiple.php +++ /dev/null @@ -1,143 +0,0 @@ -addValidator($validator); - } - - $this->type = $type; - $this->rule = $rule; - } - /** - * Add validator - * - * Add a new validator to check against during isVaid() call - * - * @param Validator $validator - * @return $this - */ - public function addValidator(Validator $validator) - { - $this->validators[] = $validator; - - return $this; - } - - /** - * Get Description - * - * Returns validator description - * - * @return string - */ - public function getDescription(): string - { - $description = ''; - foreach ($this->validators as $key => $rule) { - $description .= ++$key . '. ' . $rule->getDescription() . " \n"; - } - - return $description; - } - - /** - * Is valid - * - * Validation will pass when all rules are valid if only one of the rules is invalid validation will fail. - * - * @param mixed $value - * @return bool - */ - public function isValid(mixed $value): bool - { - foreach ($this->validators as $rule) { /* @var $rule Validator */ - $valid = $rule->isValid($value); - - // Oprimization improvements - if($this->rule === self::RULE_ALL) { - if(!$valid) { - return false; - } - } if($this->rule === self::RULE_NONE) { - if($valid) { - return false; - } - } if($this->rule === self::RULE_ANY) { - if($valid) { - return true; - } - } - } - - if($this->rule === self::RULE_ANY) { - return false; - } - - return true; - } - - /** - * Get Type - * - * Returns validator type. - * - * @return string - */ - public function getType(): string - { - return $this->type; - } - - /** - * Is array - * - * Function will return true if object is array. - * - * @return bool - */ - public function isArray(): bool - { - return true; - } -} diff --git a/src/Http/Validator/NoneOf.php b/src/Http/Validator/NoneOf.php new file mode 100644 index 00000000..97680811 --- /dev/null +++ b/src/Http/Validator/NoneOf.php @@ -0,0 +1,82 @@ + $validators + */ + public function __construct(protected array $validators, protected string $type = self::TYPE_MIXED) + { + } + + /** + * Get Description + * + * Returns validator description + * + * @return string + */ + public function getDescription(): string + { + $description = ''; + foreach ($this->validators as $key => $rule) { + $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + } + + return $description; + } + + /** + * Is valid + * + * Validation will pass when all rules are valid if only one of the rules is invalid validation will fail. + * + * @param mixed $value + * @return bool + */ + public function isValid(mixed $value): bool + { + foreach ($this->validators as $rule) { + $valid = $rule->isValid($value); + + if($valid) { + return false; + } + } + + return true; + } + + /** + * Get Type + * + * Returns validator type. + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * Is array + * + * Function will return true if object is array. + * + * @return bool + */ + public function isArray(): bool + { + return true; + } +} diff --git a/tests/Validator/MultipleTest.php b/tests/Validator/MultipleOfTest.php similarity index 60% rename from tests/Validator/MultipleTest.php rename to tests/Validator/MultipleOfTest.php index 9f1bf12d..1162ae2d 100644 --- a/tests/Validator/MultipleTest.php +++ b/tests/Validator/MultipleOfTest.php @@ -3,34 +3,34 @@ namespace Utopia\Http\Validator; use PHPUnit\Framework\TestCase; +use Utopia\Http\Validator; -class MultipleTest extends TestCase +class MultipleOfTest extends TestCase { - protected Multiple $validator; - public function setUp(): void { - $this->validator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING); } public function testIsValid() { - $this->assertEquals('string', $this->validator->getType()); - $this->assertEquals("1. Value must be a valid string and at least 1 chars and no longer than 20 chars \n2. Value must be a valid URL \n", $this->validator->getDescription()); + $validator = new AllOf([new Text(20), new URL()], Validator::TYPE_STRING); + + $this->assertEquals('string', $validator->getType()); + $this->assertEquals("1. Value must be a valid string and at least 1 chars and no longer than 20 chars \n2. Value must be a valid URL \n", $validator->getDescription()); // Valid URL but invalid text length - $this->assertFalse($this->validator->isValid('http://example.com/very-long-url')); + $this->assertFalse($validator->isValid('http://example.com/very-long-url')); // Valid text within length, but invalid URL - $this->assertFalse($this->validator->isValid('hello world')); + $this->assertFalse($validator->isValid('hello world')); // Both conditions satisfied - $this->assertTrue($this->validator->isValid('http://example.com')); - $this->assertTrue($this->validator->isValid('https://google.com')); + $this->assertTrue($validator->isValid('http://example.com')); + $this->assertTrue($validator->isValid('https://google.com')); // Neither condition satisfied - $this->assertFalse($this->validator->isValid('example.com/hello-world')); - $this->assertFalse($this->validator->isValid('')); + $this->assertFalse($validator->isValid('example.com/hello-world')); + $this->assertFalse($validator->isValid('')); } public function testRules() @@ -40,19 +40,19 @@ public function testRules() $invalidTextValidUrl = 'http://example.com/very-long-url'; $invalidTextInvalidUrl = 'Some very long text that is also not an URL'; - $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_ALL); + $vaidator = new AllOf([new Text(20), new URL()], Validator::TYPE_STRING); $this->assertTrue($vaidator->isValid($validTextValidUrl)); $this->assertFalse($vaidator->isValid($validTextInvalidUrl)); $this->assertFalse($vaidator->isValid($invalidTextValidUrl)); $this->assertFalse($vaidator->isValid($invalidTextInvalidUrl)); - $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_ANY); + $vaidator = new AnyOf([new Text(20), new URL()], Validator::TYPE_STRING); $this->assertTrue($vaidator->isValid($validTextValidUrl)); $this->assertTrue($vaidator->isValid($validTextInvalidUrl)); $this->assertTrue($vaidator->isValid($invalidTextValidUrl)); $this->assertFalse($vaidator->isValid($invalidTextInvalidUrl)); - $vaidator = new Multiple([new Text(20), new URL()], Multiple::TYPE_STRING, Multiple::RULE_NONE); + $vaidator = new NoneOf([new Text(20), new URL()], Validator::TYPE_STRING); $this->assertFalse($vaidator->isValid($validTextValidUrl)); $this->assertFalse($vaidator->isValid($validTextInvalidUrl)); $this->assertFalse($vaidator->isValid($invalidTextValidUrl)); From f60479fc740fe41596924b313bb60c6423fcc144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 14:59:34 +0000 Subject: [PATCH 59/71] PR review changes --- src/Http/Validator/AllOf.php | 8 ++++++-- src/Http/Validator/AnyOf.php | 9 +++++++-- src/Http/Validator/NoneOf.php | 8 ++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Http/Validator/AllOf.php b/src/Http/Validator/AllOf.php index 84cd8f9f..f73dd156 100644 --- a/src/Http/Validator/AllOf.php +++ b/src/Http/Validator/AllOf.php @@ -11,6 +11,8 @@ */ class AllOf extends Validator { + protected ?Validator $failedRule = null; + /** * @param array $validators */ @@ -28,8 +30,9 @@ public function __construct(protected array $validators, protected string $type public function getDescription(): string { $description = ''; - foreach ($this->validators as $key => $rule) { - $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + + if(!(\is_null($this->failedRule))) { + $description .= $this->failedRule->getDescription(); } return $description; @@ -49,6 +52,7 @@ public function isValid(mixed $value): bool $valid = $rule->isValid($value); if(!$valid) { + $this->failedRule = $rule; return false; } } diff --git a/src/Http/Validator/AnyOf.php b/src/Http/Validator/AnyOf.php index 253891dc..780b9a59 100644 --- a/src/Http/Validator/AnyOf.php +++ b/src/Http/Validator/AnyOf.php @@ -11,6 +11,8 @@ */ class AnyOf extends Validator { + protected ?Validator $failedRule = null; + /** * @param array $validators */ @@ -28,8 +30,9 @@ public function __construct(protected array $validators, protected string $type public function getDescription(): string { $description = ''; - foreach ($this->validators as $key => $rule) { - $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + + if(!(\is_null($this->failedRule))) { + $description .= $this->failedRule->getDescription(); } return $description; @@ -48,6 +51,8 @@ public function isValid(mixed $value): bool foreach ($this->validators as $rule) { $valid = $rule->isValid($value); + $this->failedRule = $rule; + if($valid) { return true; } diff --git a/src/Http/Validator/NoneOf.php b/src/Http/Validator/NoneOf.php index 97680811..240d9271 100644 --- a/src/Http/Validator/NoneOf.php +++ b/src/Http/Validator/NoneOf.php @@ -11,6 +11,8 @@ */ class NoneOf extends Validator { + protected ?Validator $failedRule = null; + /** * @param array $validators */ @@ -28,8 +30,9 @@ public function __construct(protected array $validators, protected string $type public function getDescription(): string { $description = ''; - foreach ($this->validators as $key => $rule) { - $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + + if(!(\is_null($this->failedRule))) { + $description .= $this->failedRule->getDescription(); } return $description; @@ -49,6 +52,7 @@ public function isValid(mixed $value): bool $valid = $rule->isValid($value); if($valid) { + $this->failedRule = $rule; return false; } } From 6ae1f18bbb2f905101317f36bf85b271063429c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 15:01:11 +0000 Subject: [PATCH 60/71] Fix tests --- tests/Validator/MultipleOfTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Validator/MultipleOfTest.php b/tests/Validator/MultipleOfTest.php index 1162ae2d..f8e9bb37 100644 --- a/tests/Validator/MultipleOfTest.php +++ b/tests/Validator/MultipleOfTest.php @@ -16,7 +16,7 @@ public function testIsValid() $validator = new AllOf([new Text(20), new URL()], Validator::TYPE_STRING); $this->assertEquals('string', $validator->getType()); - $this->assertEquals("1. Value must be a valid string and at least 1 chars and no longer than 20 chars \n2. Value must be a valid URL \n", $validator->getDescription()); + $this->assertEquals("1Value must be a valid string and at least 1 chars and no longer than 20 chars", $validator->getDescription()); // Valid URL but invalid text length $this->assertFalse($validator->isValid('http://example.com/very-long-url')); From ed89b1991f5882a4fdd9ba700effb8f5b98675eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 15:04:37 +0000 Subject: [PATCH 61/71] Fix CI/CD --- src/Http/Validator/AllOf.php | 6 +++--- src/Http/Validator/AnyOf.php | 6 +++--- src/Http/Validator/NoneOf.php | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Http/Validator/AllOf.php b/src/Http/Validator/AllOf.php index f73dd156..70b40751 100644 --- a/src/Http/Validator/AllOf.php +++ b/src/Http/Validator/AllOf.php @@ -29,10 +29,10 @@ public function __construct(protected array $validators, protected string $type */ public function getDescription(): string { - $description = ''; - if(!(\is_null($this->failedRule))) { - $description .= $this->failedRule->getDescription(); + $description = $this->failedRule->getDescription(); + } else { + $description = $this->validators[0]->getDescription(); } return $description; diff --git a/src/Http/Validator/AnyOf.php b/src/Http/Validator/AnyOf.php index 780b9a59..ad2bd921 100644 --- a/src/Http/Validator/AnyOf.php +++ b/src/Http/Validator/AnyOf.php @@ -29,10 +29,10 @@ public function __construct(protected array $validators, protected string $type */ public function getDescription(): string { - $description = ''; - if(!(\is_null($this->failedRule))) { - $description .= $this->failedRule->getDescription(); + $description = $this->failedRule->getDescription(); + } else { + $description = $this->validators[0]->getDescription(); } return $description; diff --git a/src/Http/Validator/NoneOf.php b/src/Http/Validator/NoneOf.php index 240d9271..20af51b7 100644 --- a/src/Http/Validator/NoneOf.php +++ b/src/Http/Validator/NoneOf.php @@ -32,7 +32,9 @@ public function getDescription(): string $description = ''; if(!(\is_null($this->failedRule))) { - $description .= $this->failedRule->getDescription(); + $description = $this->failedRule->getDescription(); + } else { + $description = $this->validators[0]->getDescription(); } return $description; From 726540d0bda3253f9ef628fd510dc13289938c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 2 Jul 2024 15:06:19 +0000 Subject: [PATCH 62/71] Typo --- tests/Validator/MultipleOfTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Validator/MultipleOfTest.php b/tests/Validator/MultipleOfTest.php index f8e9bb37..06435aa8 100644 --- a/tests/Validator/MultipleOfTest.php +++ b/tests/Validator/MultipleOfTest.php @@ -16,7 +16,7 @@ public function testIsValid() $validator = new AllOf([new Text(20), new URL()], Validator::TYPE_STRING); $this->assertEquals('string', $validator->getType()); - $this->assertEquals("1Value must be a valid string and at least 1 chars and no longer than 20 chars", $validator->getDescription()); + $this->assertEquals("Value must be a valid string and at least 1 chars and no longer than 20 chars", $validator->getDescription()); // Valid URL but invalid text length $this->assertFalse($validator->isValid('http://example.com/very-long-url')); From 6d5c75a042e7a01c5896237e28f5411fd80c9d88 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:33:22 -0400 Subject: [PATCH 63/71] feat: adding Coroutine server --- Dockerfile.swoole_coroutines | 48 +++ docker-compose.yml | 17 +- src/Http/Adapter/SwooleCoroutine/Request.php | 364 ++++++++++++++++++ src/Http/Adapter/SwooleCoroutine/Response.php | 99 +++++ src/Http/Adapter/SwooleCoroutine/Server.php | 51 +++ tests/e2e/server-swoole-coroutine.php | 52 +++ 6 files changed, 629 insertions(+), 2 deletions(-) create mode 100644 Dockerfile.swoole_coroutines create mode 100644 src/Http/Adapter/SwooleCoroutine/Request.php create mode 100644 src/Http/Adapter/SwooleCoroutine/Response.php create mode 100644 src/Http/Adapter/SwooleCoroutine/Server.php create mode 100644 tests/e2e/server-swoole-coroutine.php diff --git a/Dockerfile.swoole_coroutines b/Dockerfile.swoole_coroutines new file mode 100644 index 00000000..a02852da --- /dev/null +++ b/Dockerfile.swoole_coroutines @@ -0,0 +1,48 @@ +FROM composer:2.0 AS step0 + +ARG TESTING=true +ARG DEBUG=false + +ENV TESTING=$TESTING +ENV DEBUG=$DEBUG + +WORKDIR /usr/local/src/ + +COPY composer.* /usr/local/src/ + +RUN composer install --ignore-platform-reqs --optimize-autoloader \ + --no-plugins --no-scripts --prefer-dist \ + `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` + +FROM appwrite/base:0.9.0 as final + +ARG TESTING=true +ARG DEBUG=false + +ENV TESTING=$TESTING +ENV DEBUG=$DEBUG + +LABEL maintainer="team@appwrite.io" + +RUN \ + if [ "$DEBUG" == "true" ]; then \ + apk add boost boost-dev; \ + fi + +WORKDIR /usr/src/code + +COPY ./dev /usr/src/code/dev +COPY ./src /usr/src/code/src +COPY ./tests /usr/src/code/tests +COPY ./phpunit.xml /usr/src/code/phpunit.xml +COPY ./phpbench.json /usr/src/code/phpbench.json +COPY --from=step0 /usr/local/src/vendor /usr/src/code/vendor + +# Enable Extensions +RUN if [ "$DEBUG" == "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi +RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi +RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi + +EXPOSE 80 + +CMD ["php", "tests/e2e/server-swoole-coroutine.php"] diff --git a/docker-compose.yml b/docker-compose.yml index 744621f0..bd2952c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: build: context: . dockerfile: Dockerfile.swoole - ports: + ports: - "9401:80" volumes: - ./dev:/usr/src/code/dev:rw @@ -25,6 +25,19 @@ services: - ./tmp/xdebug:/tmp/xdebug networks: - testing + swoole-coroutine: + build: + context: . + dockerfile: Dockerfile.swoole_coroutines + ports: + - "9402:80" + volumes: + - ./dev:/usr/src/code/dev:rw + - ./src:/usr/src/code/src + - ./tests:/usr/src/code/tests + - ./tmp/xdebug:/tmp/xdebug + networks: + - testing mariadb: image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p @@ -41,4 +54,4 @@ services: command: "mysqld --innodb-flush-method=fsync --max-connections=10000" networks: - testing: \ No newline at end of file + testing: diff --git a/src/Http/Adapter/SwooleCoroutine/Request.php b/src/Http/Adapter/SwooleCoroutine/Request.php new file mode 100644 index 00000000..1659b743 --- /dev/null +++ b/src/Http/Adapter/SwooleCoroutine/Request.php @@ -0,0 +1,364 @@ +swoole = $request; + } + + /** + * Get raw payload + * + * Method for getting the HTTP request payload as a raw string. + * + * @return string + */ + public function getRawPayload(): string + { + return $this->swoole->rawContent(); + } + + /** + * Get server + * + * Method for querying server parameters. If $key is not found $default value will be returned. + * + * @param string $key + * @param string|null $default + * @return string|null + */ + public function getServer(string $key, string $default = null): ?string + { + return $this->swoole->server[$key] ?? $default; + } + + /** + * Set server + * + * Method for setting server parameters. + * + * @param string $key + * @param string $value + * @return static + */ + public function setServer(string $key, string $value): static + { + $this->swoole->server[$key] = $value; + + return $this; + } + + /** + * Get IP + * + * Returns users IP address. + * Support HTTP_X_FORWARDED_FOR header usually return + * from different proxy servers or PHP default REMOTE_ADDR + */ + public function getIP(): string + { + $ips = explode(',', $this->getHeader('x-forwarded-for', $this->getServer('remote_addr') ?? '0.0.0.0')); + + return trim($ips[0] ?? ''); + } + + /** + * Get Protocol + * + * Returns request protocol. + * Support HTTP_X_FORWARDED_PROTO header usually return + * from different proxy servers or PHP default REQUEST_SCHEME + * + * @return string + */ + public function getProtocol(): string + { + $protocol = $this->getHeader('x-forwarded-proto', $this->getServer('server_protocol') ?? 'https'); + + if ($protocol === 'HTTP/1.1') { + return 'http'; + } + + return match ($protocol) { + 'http', 'https', 'ws', 'wss' => $protocol, + default => 'https' + }; + } + + /** + * Get Port + * + * Returns request port. + * + * @return 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)); + } + + /** + * Get Hostname + * + * Returns request hostname. + * + * @return string + */ + public function getHostname(): string + { + return strval(\parse_url($this->getProtocol().'://'.$this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_HOST)); + } + + /** + * Get Method + * + * Return HTTP request method + * + * @return string + */ + public function getMethod(): string + { + return $this->getServer('request_method') ?? 'UNKNOWN'; + } + + /** + * Set method + * + * Set HTTP request method + * + * @param string $method + * @return static + */ + public function setMethod(string $method): static + { + $this->setServer('request_method', $method); + + return $this; + } + + /** + * Get URI + * + * Return HTTP request URI + * + * @return string + */ + public function getURI(): string + { + return $this->getServer('request_uri') ?? ''; + } + + /** + * Set URI + * + * Set HTTP request URI + * + * @param string $uri + * @return static + */ + public function setURI(string $uri): static + { + $this->setServer('request_uri', $uri); + + return $this; + } + + /** + * Get Referer + * + * Return HTTP referer header + * + * @return string + */ + public function getReferer(string $default = ''): string + { + return $this->getHeader('referer', ''); + } + + /** + * Get Origin + * + * Return HTTP origin header + * + * @return string + */ + public function getOrigin(string $default = ''): string + { + return $this->getHeader('origin', $default); + } + + /** + * Get User Agent + * + * Return HTTP user agent header + * + * @return string + */ + public function getUserAgent(string $default = ''): string + { + return $this->getHeader('user-agent', $default); + } + + /** + * Get Accept + * + * Return HTTP accept header + * + * @return string + */ + public function getAccept(string $default = ''): string + { + return $this->getHeader('accept', $default); + } + + /** + * Get files + * + * Method for querying upload files data. If $key is not found empty array will be returned. + * + * @param string $key + * @return array + */ + public function getFiles($key): array + { + $key = strtolower($key); + + return $this->swoole->files[$key] ?? []; + } + + /** + * Get cookie + * + * Method for querying HTTP cookie parameters. If $key is not found $default value will be returned. + * + * @param string $key + * @param string $default + * @return string + */ + public function getCookie(string $key, string $default = ''): string + { + $key = strtolower($key); + + return $this->swoole->cookie[$key] ?? $default; + } + + /** + * Get header + * + * Method for querying HTTP header parameters. If $key is not found $default value will be returned. + * + * @param string $key + * @param string $default + * @return string + */ + public function getHeader(string $key, string $default = ''): string + { + return $this->swoole->header[$key] ?? $default; + } + + /** + * Method for adding HTTP header parameters. + * + * @param string $key + * @param string $value + * @return static + */ + public function addHeader(string $key, string $value): static + { + $this->swoole->header[$key] = $value; + + return $this; + } + + /** + * Method for removing HTTP header parameters. + * + * @param string $key + * @return static + */ + public function removeHeader(string $key): static + { + if (isset($this->swoole->header[$key])) { + unset($this->swoole->header[$key]); + } + + return $this; + } + + public function getSwooleRequest(): SwooleRequest + { + return $this->swoole; + } + + /** + * Generate input + * + * Generate PHP input stream and parse it as an array in order to handle different content type of requests + * + * @return array + */ + protected function generateInput(): array + { + if (null === $this->queryString) { + $this->queryString = $this->swoole->get ?? []; + } + if (null === $this->payload) { + $contentType = $this->getHeader('content-type'); + + // Get content-type without the charset + $length = strpos($contentType, ';'); + $length = (empty($length)) ? strlen($contentType) : $length; + $contentType = substr($contentType, 0, $length); + + switch ($contentType) { + case 'application/json': + $this->payload = json_decode(strval($this->swoole->rawContent()), true); + break; + + default: + $this->payload = $this->swoole->post; + break; + } + + if (empty($this->payload)) { // Make sure we return same data type even if json payload is empty or failed + $this->payload = []; + } + } + + return match ($this->getMethod()) { + self::METHOD_POST, + self::METHOD_PUT, + self::METHOD_PATCH, + self::METHOD_DELETE => $this->payload, + default => $this->queryString + }; + } + + /** + * Generate headers + * + * Parse request headers as an array for easy querying using the getHeader method + * + * @return array + */ + protected function generateHeaders(): array + { + return $this->swoole->header; + } +} diff --git a/src/Http/Adapter/SwooleCoroutine/Response.php b/src/Http/Adapter/SwooleCoroutine/Response.php new file mode 100644 index 00000000..2c8c77a7 --- /dev/null +++ b/src/Http/Adapter/SwooleCoroutine/Response.php @@ -0,0 +1,99 @@ +swoole = $response; + parent::__construct(\microtime(true)); + } + + public function getSwooleResponse(): SwooleResponse + { + return $this->swoole; + } + + /** + * Write + * + * @param string $content + * @return bool False if write cannot complete, such as request ended by client + */ + public function write(string $content): bool + { + return $this->swoole->write($content); + } + + /** + * End + * + * @param string|null $content + * @return void + */ + public function end(string $content = null): void + { + $this->swoole->end($content); + } + + /** + * Send Status Code + * + * @param int $statusCode + * @return void + */ + protected function sendStatus(int $statusCode): void + { + $this->swoole->status((string) $statusCode); + } + + /** + * Send Header + * + * @param string $key + * @param string $value + * @return void + */ + public function sendHeader(string $key, string $value): void + { + $this->swoole->header($key, $value); + } + + /** + * Send Cookie + * + * Send a cookie + * + * @param string $name + * @param string $value + * @param array $options + * @return void + */ + protected function sendCookie(string $name, string $value, array $options): void + { + $this->swoole->cookie( + name: $name, + value: $value, + expires: $options['expire'] ?? 0, + path: $options['path'] ?? '', + domain: $options['domain'] ?? '', + secure: $options['secure'] ?? false, + httponly: $options['httponly'] ?? false, + samesite: $options['samesite'] ?? false, + ); + } +} diff --git a/src/Http/Adapter/SwooleCoroutine/Server.php b/src/Http/Adapter/SwooleCoroutine/Server.php new file mode 100644 index 00000000..d813172f --- /dev/null +++ b/src/Http/Adapter/SwooleCoroutine/Server.php @@ -0,0 +1,51 @@ +server = new SwooleServer($host, $port); + $this->server->set(\array_merge($settings, [ + 'enable_coroutine' => true + ])); + } + + public function onRequest(callable $callback) + { + $this->server->handle('/', function (SwooleRequest $request, SwooleResponse $response) use ($callback) { + $context = \strval(Coroutine::getCid()); + + Http::setResource('swooleRequest', fn () => $request, [], $context); + Http::setResource('swooleResponse', fn () => $response, [], $context); + + call_user_func($callback, new Request($request), new Response($response), $context); + }); + } + + public function onStart(callable $callback) + { + call_user_func($callback, $this); + } + + public function start() + { + if(Coroutine::getCid() === -1) { + run(fn () => $this->server->start()); + } else { + $this->server->start(); + } + } +} diff --git a/tests/e2e/server-swoole-coroutine.php b/tests/e2e/server-swoole-coroutine.php new file mode 100644 index 00000000..58995168 --- /dev/null +++ b/tests/e2e/server-swoole-coroutine.php @@ -0,0 +1,52 @@ +withHost('mariadb') + ->withPort(3306) + // ->withUnixSocket('/tmp/mysql.sock') + ->withDbName('test') + ->withCharset('utf8mb4') + ->withUsername('user') + ->withPassword('password'), 9000); + + +$dependency = new Dependency(); + +$dependency + ->setName('key') + ->inject('request') + ->setCallback(function (Request $request) { + return $request->getHeader('x-utopia-key', 'unknown'); + }); + +$container->set($dependency); + +$dependency1 = new Dependency(); +$dependency1 + ->setName('pool') + ->setCallback(function () use ($pool) { + return $pool; + }); + +$container->set($dependency1); + +$server = new Server('0.0.0.0', '80'); +$http = new Http($server, $container, 'UTC'); + +echo "Server started\n"; + +$http->start(); From 13976741c6e3734bd8caa757eb95878a6706a132 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:51:16 -0400 Subject: [PATCH 64/71] feat: adding Coroutine server --- src/Http/Adapter/SwooleCoroutine/Request.php | 357 +----------------- src/Http/Adapter/SwooleCoroutine/Response.php | 92 +---- src/Http/Adapter/SwooleCoroutine/Server.php | 23 +- 3 files changed, 9 insertions(+), 463 deletions(-) diff --git a/src/Http/Adapter/SwooleCoroutine/Request.php b/src/Http/Adapter/SwooleCoroutine/Request.php index 1659b743..7b63ab69 100644 --- a/src/Http/Adapter/SwooleCoroutine/Request.php +++ b/src/Http/Adapter/SwooleCoroutine/Request.php @@ -2,363 +2,8 @@ namespace Utopia\Http\Adapter\SwooleCoroutine; -use Swoole\Http\Request as SwooleRequest; -use Utopia\Http\Request as UtopiaRequest; +use Utopia\Http\Adapter\Swoole\Request as UtopiaRequest; class Request extends UtopiaRequest { - /** - * Swoole Request Object - * - * @var SwooleRequest - */ - protected SwooleRequest $swoole; - - /** - * Request constructor. - */ - public function __construct(SwooleRequest $request) - { - $this->swoole = $request; - } - - /** - * Get raw payload - * - * Method for getting the HTTP request payload as a raw string. - * - * @return string - */ - public function getRawPayload(): string - { - return $this->swoole->rawContent(); - } - - /** - * Get server - * - * Method for querying server parameters. If $key is not found $default value will be returned. - * - * @param string $key - * @param string|null $default - * @return string|null - */ - public function getServer(string $key, string $default = null): ?string - { - return $this->swoole->server[$key] ?? $default; - } - - /** - * Set server - * - * Method for setting server parameters. - * - * @param string $key - * @param string $value - * @return static - */ - public function setServer(string $key, string $value): static - { - $this->swoole->server[$key] = $value; - - return $this; - } - - /** - * Get IP - * - * Returns users IP address. - * Support HTTP_X_FORWARDED_FOR header usually return - * from different proxy servers or PHP default REMOTE_ADDR - */ - public function getIP(): string - { - $ips = explode(',', $this->getHeader('x-forwarded-for', $this->getServer('remote_addr') ?? '0.0.0.0')); - - return trim($ips[0] ?? ''); - } - - /** - * Get Protocol - * - * Returns request protocol. - * Support HTTP_X_FORWARDED_PROTO header usually return - * from different proxy servers or PHP default REQUEST_SCHEME - * - * @return string - */ - public function getProtocol(): string - { - $protocol = $this->getHeader('x-forwarded-proto', $this->getServer('server_protocol') ?? 'https'); - - if ($protocol === 'HTTP/1.1') { - return 'http'; - } - - return match ($protocol) { - 'http', 'https', 'ws', 'wss' => $protocol, - default => 'https' - }; - } - - /** - * Get Port - * - * Returns request port. - * - * @return 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)); - } - - /** - * Get Hostname - * - * Returns request hostname. - * - * @return string - */ - public function getHostname(): string - { - return strval(\parse_url($this->getProtocol().'://'.$this->getHeader('x-forwarded-host', $this->getHeader('host')), PHP_URL_HOST)); - } - - /** - * Get Method - * - * Return HTTP request method - * - * @return string - */ - public function getMethod(): string - { - return $this->getServer('request_method') ?? 'UNKNOWN'; - } - - /** - * Set method - * - * Set HTTP request method - * - * @param string $method - * @return static - */ - public function setMethod(string $method): static - { - $this->setServer('request_method', $method); - - return $this; - } - - /** - * Get URI - * - * Return HTTP request URI - * - * @return string - */ - public function getURI(): string - { - return $this->getServer('request_uri') ?? ''; - } - - /** - * Set URI - * - * Set HTTP request URI - * - * @param string $uri - * @return static - */ - public function setURI(string $uri): static - { - $this->setServer('request_uri', $uri); - - return $this; - } - - /** - * Get Referer - * - * Return HTTP referer header - * - * @return string - */ - public function getReferer(string $default = ''): string - { - return $this->getHeader('referer', ''); - } - - /** - * Get Origin - * - * Return HTTP origin header - * - * @return string - */ - public function getOrigin(string $default = ''): string - { - return $this->getHeader('origin', $default); - } - - /** - * Get User Agent - * - * Return HTTP user agent header - * - * @return string - */ - public function getUserAgent(string $default = ''): string - { - return $this->getHeader('user-agent', $default); - } - - /** - * Get Accept - * - * Return HTTP accept header - * - * @return string - */ - public function getAccept(string $default = ''): string - { - return $this->getHeader('accept', $default); - } - - /** - * Get files - * - * Method for querying upload files data. If $key is not found empty array will be returned. - * - * @param string $key - * @return array - */ - public function getFiles($key): array - { - $key = strtolower($key); - - return $this->swoole->files[$key] ?? []; - } - - /** - * Get cookie - * - * Method for querying HTTP cookie parameters. If $key is not found $default value will be returned. - * - * @param string $key - * @param string $default - * @return string - */ - public function getCookie(string $key, string $default = ''): string - { - $key = strtolower($key); - - return $this->swoole->cookie[$key] ?? $default; - } - - /** - * Get header - * - * Method for querying HTTP header parameters. If $key is not found $default value will be returned. - * - * @param string $key - * @param string $default - * @return string - */ - public function getHeader(string $key, string $default = ''): string - { - return $this->swoole->header[$key] ?? $default; - } - - /** - * Method for adding HTTP header parameters. - * - * @param string $key - * @param string $value - * @return static - */ - public function addHeader(string $key, string $value): static - { - $this->swoole->header[$key] = $value; - - return $this; - } - - /** - * Method for removing HTTP header parameters. - * - * @param string $key - * @return static - */ - public function removeHeader(string $key): static - { - if (isset($this->swoole->header[$key])) { - unset($this->swoole->header[$key]); - } - - return $this; - } - - public function getSwooleRequest(): SwooleRequest - { - return $this->swoole; - } - - /** - * Generate input - * - * Generate PHP input stream and parse it as an array in order to handle different content type of requests - * - * @return array - */ - protected function generateInput(): array - { - if (null === $this->queryString) { - $this->queryString = $this->swoole->get ?? []; - } - if (null === $this->payload) { - $contentType = $this->getHeader('content-type'); - - // Get content-type without the charset - $length = strpos($contentType, ';'); - $length = (empty($length)) ? strlen($contentType) : $length; - $contentType = substr($contentType, 0, $length); - - switch ($contentType) { - case 'application/json': - $this->payload = json_decode(strval($this->swoole->rawContent()), true); - break; - - default: - $this->payload = $this->swoole->post; - break; - } - - if (empty($this->payload)) { // Make sure we return same data type even if json payload is empty or failed - $this->payload = []; - } - } - - return match ($this->getMethod()) { - self::METHOD_POST, - self::METHOD_PUT, - self::METHOD_PATCH, - self::METHOD_DELETE => $this->payload, - default => $this->queryString - }; - } - - /** - * Generate headers - * - * Parse request headers as an array for easy querying using the getHeader method - * - * @return array - */ - protected function generateHeaders(): array - { - return $this->swoole->header; - } } diff --git a/src/Http/Adapter/SwooleCoroutine/Response.php b/src/Http/Adapter/SwooleCoroutine/Response.php index 2c8c77a7..82701248 100644 --- a/src/Http/Adapter/SwooleCoroutine/Response.php +++ b/src/Http/Adapter/SwooleCoroutine/Response.php @@ -2,98 +2,8 @@ namespace Utopia\Http\Adapter\SwooleCoroutine; -use Swoole\Http\Response as SwooleResponse; -use Utopia\Http\Response as UtopiaResponse; +use Utopia\Http\Adapter\Swoole\Response as UtopiaResponse; class Response extends UtopiaResponse { - /** - * Swoole Response Object - * - * @var SwooleResponse - */ - protected $swoole; - - /** - * Response constructor. - */ - public function __construct(SwooleResponse $response) - { - $this->swoole = $response; - parent::__construct(\microtime(true)); - } - - public function getSwooleResponse(): SwooleResponse - { - return $this->swoole; - } - - /** - * Write - * - * @param string $content - * @return bool False if write cannot complete, such as request ended by client - */ - public function write(string $content): bool - { - return $this->swoole->write($content); - } - - /** - * End - * - * @param string|null $content - * @return void - */ - public function end(string $content = null): void - { - $this->swoole->end($content); - } - - /** - * Send Status Code - * - * @param int $statusCode - * @return void - */ - protected function sendStatus(int $statusCode): void - { - $this->swoole->status((string) $statusCode); - } - - /** - * Send Header - * - * @param string $key - * @param string $value - * @return void - */ - public function sendHeader(string $key, string $value): void - { - $this->swoole->header($key, $value); - } - - /** - * Send Cookie - * - * Send a cookie - * - * @param string $name - * @param string $value - * @param array $options - * @return void - */ - protected function sendCookie(string $name, string $value, array $options): void - { - $this->swoole->cookie( - name: $name, - value: $value, - expires: $options['expire'] ?? 0, - path: $options['path'] ?? '', - domain: $options['domain'] ?? '', - secure: $options['secure'] ?? false, - httponly: $options['httponly'] ?? false, - samesite: $options['samesite'] ?? false, - ); - } } diff --git a/src/Http/Adapter/SwooleCoroutine/Server.php b/src/Http/Adapter/SwooleCoroutine/Server.php index d813172f..5ab97476 100644 --- a/src/Http/Adapter/SwooleCoroutine/Server.php +++ b/src/Http/Adapter/SwooleCoroutine/Server.php @@ -2,12 +2,8 @@ namespace Utopia\Http\Adapter\SwooleCoroutine; -use Swoole\Coroutine; use Utopia\Http\Adapter; use Swoole\Coroutine\Http\Server as SwooleServer; -use Swoole\Http\Request as SwooleRequest; -use Swoole\Http\Response as SwooleResponse; -use Utopia\Http\Http; use function Swoole\Coroutine\run; @@ -25,27 +21,22 @@ public function __construct(string $host, string $port = null, array $settings = public function onRequest(callable $callback) { - $this->server->handle('/', function (SwooleRequest $request, SwooleResponse $response) use ($callback) { - $context = \strval(Coroutine::getCid()); - - Http::setResource('swooleRequest', fn () => $request, [], $context); - Http::setResource('swooleResponse', fn () => $response, [], $context); - - call_user_func($callback, new Request($request), new Response($response), $context); + $this->server->handle('/', function ($request, $response) use ($callback) { + call_user_func($callback, new Request($request), new Response($response)); }); } public function onStart(callable $callback) { - call_user_func($callback, $this); + go(function () use ($callback) { + call_user_func($callback, $this); + }); } public function start() { - if(Coroutine::getCid() === -1) { - run(fn () => $this->server->start()); - } else { + go(function () { $this->server->start(); - } + }); } } From f4ce8a42a5613f40992e6fe84ff2e23584465adb Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:21:21 -0400 Subject: [PATCH 65/71] feat: adding Coroutine server --- src/Http/Adapter/SwooleCoroutine/Server.php | 12 +++++------- src/Http/Http.php | 8 +------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/Http/Adapter/SwooleCoroutine/Server.php b/src/Http/Adapter/SwooleCoroutine/Server.php index 5ab97476..c3a8f545 100644 --- a/src/Http/Adapter/SwooleCoroutine/Server.php +++ b/src/Http/Adapter/SwooleCoroutine/Server.php @@ -5,15 +5,13 @@ use Utopia\Http\Adapter; use Swoole\Coroutine\Http\Server as SwooleServer; -use function Swoole\Coroutine\run; - class Server extends Adapter { protected SwooleServer $server; public function __construct(string $host, string $port = null, array $settings = []) { - $this->server = new SwooleServer($host, $port); + $this->server = new SwooleServer($host, $port, false, true); $this->server->set(\array_merge($settings, [ 'enable_coroutine' => true ])); @@ -22,15 +20,15 @@ public function __construct(string $host, string $port = null, array $settings = public function onRequest(callable $callback) { $this->server->handle('/', function ($request, $response) use ($callback) { - call_user_func($callback, new Request($request), new Response($response)); + go(function () use ($request, $response, $callback) { + call_user_func($callback, new Request($request), new Response($response)); + }); }); } public function onStart(callable $callback) { - go(function () use ($callback) { - call_user_func($callback, $this); - }); + call_user_func($callback, $this); } public function start() diff --git a/src/Http/Http.php b/src/Http/Http.php index e2726c82..dbe8fd0e 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -335,13 +335,7 @@ public function start() clone $dependency ->setName('http') ->setCallback(fn () => $this) - ) - ->set( - clone $dependency - ->setName('context') - ->setCallback(fn () => $context) - ) - ; + ); $this->run($context); }); From d72069f810521fd90a378791adc7e1cf8fc9a378 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:01:24 -0400 Subject: [PATCH 66/71] feat: GraphQL injections and tests --- .github/workflows/test.yml | 5 +- composer.lock | 255 +++++++++++----------- src/Http/Http.php | 102 ++++----- tests/HttpTest.php | 40 ++-- tests/e2e/ResponseSwooleCoroutineTest.php | 17 ++ 5 files changed, 206 insertions(+), 213 deletions(-) create mode 100644 tests/e2e/ResponseSwooleCoroutineTest.php diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e17e5507..ca3b5885 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,4 +28,7 @@ jobs: run: docker compose exec fpm vendor/bin/phpunit --configuration phpunit.xml - name: Run Swoole Tests - run: docker compose exec swoole vendor/bin/phpunit --configuration phpunit.xml \ No newline at end of file + run: docker compose exec swoole vendor/bin/phpunit --configuration phpunit.xml + + - name: Run Swoole Corotuine Tests + run: docker compose exec swoole-coroutine vendor/bin/phpunit --configuration phpunit.xml diff --git a/composer.lock b/composer.lock index 265089bc..5ceeb87d 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "utopia-php/di", - "version": "dev-main", + "version": "dev-feat-framework-v2", "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "a0c8be65c19570c80e904d58f54bdd901d1d5d9c" + "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/a0c8be65c19570c80e904d58f54bdd901d1d5d9c", - "reference": "a0c8be65c19570c80e904d58f54bdd901d1d5d9c", + "url": "https://api.github.com/repos/utopia-php/di/zipball/1fb7da5ead16de5d795ef10c1e22e39726eb6943", + "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943", "shasum": "" }, "require": { @@ -30,7 +30,6 @@ "phpunit/phpunit": "^9.5.25", "swoole/ide-helper": "4.8.3" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -63,10 +62,10 @@ "upf" ], "support": { - "source": "https://github.com/utopia-php/di/tree/main", + "source": "https://github.com/utopia-php/di/tree/feat-framework-v2", "issues": "https://github.com/utopia-php/di/issues" }, - "time": "2024-04-22T21:22:44+00:00" + "time": "2024-06-11T16:03:00+00:00" }, { "name": "utopia-php/servers", @@ -74,17 +73,17 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "e7eee7f82399c89adc28cf79912a9a41d7bb3233" + "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/e7eee7f82399c89adc28cf79912a9a41d7bb3233", - "reference": "e7eee7f82399c89adc28cf79912a9a41d7bb3233", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/4565c1c111f6da6b18bc0f00f350377a1e691e48", + "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/di": "dev-main" + "utopia-php/di": "dev-feat-framework-v2" }, "require-dev": { "laravel/pint": "^0.2.3", @@ -137,7 +136,7 @@ "source": "https://github.com/utopia-php/servers/tree/dev", "issues": "https://github.com/utopia-php/servers/issues" }, - "time": "2024-04-22T21:23:28+00:00" + "time": "2024-06-07T18:49:59+00:00" } ], "packages-dev": [ @@ -224,12 +223,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e" + "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", - "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", + "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", "shasum": "" }, "require": { @@ -287,7 +286,7 @@ "type": "tidelift" } ], - "time": "2023-12-09T14:19:21+00:00" + "time": "2024-06-20T19:34:15+00:00" }, { "name": "doctrine/lexer", @@ -368,16 +367,16 @@ }, { "name": "laravel/pint", - "version": "v1.15.1", + "version": "v1.16.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "5f288b5e79938cc72f5c298d384e639de87507c6" + "reference": "9266a47f1b9231b83e0cfd849009547329d871b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/5f288b5e79938cc72f5c298d384e639de87507c6", - "reference": "5f288b5e79938cc72f5c298d384e639de87507c6", + "url": "https://api.github.com/repos/laravel/pint/zipball/9266a47f1b9231b83e0cfd849009547329d871b1", + "reference": "9266a47f1b9231b83e0cfd849009547329d871b1", "shasum": "" }, "require": { @@ -388,13 +387,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.52.1", - "illuminate/view": "^10.48.4", - "larastan/larastan": "^2.9.2", - "laravel-zero/framework": "^10.3.0", - "mockery/mockery": "^1.6.11", + "friendsofphp/php-cs-fixer": "^3.59.3", + "illuminate/view": "^10.48.12", + "larastan/larastan": "^2.9.7", + "laravel-zero/framework": "^10.4.0", + "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.34.5" + "pestphp/pest": "^2.34.8" }, "bin": [ "builds/pint" @@ -430,7 +429,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-04-02T14:28:47+00:00" + "time": "2024-06-18T16:50:05+00:00" }, { "name": "myclabs/deep-copy", @@ -438,12 +437,12 @@ "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "2f5294676c802a62b0549f6bc8983f14294ce369" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/2f5294676c802a62b0549f6bc8983f14294ce369", - "reference": "2f5294676c802a62b0549f6bc8983f14294ce369", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -483,7 +482,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.x" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -491,20 +490,20 @@ "type": "tidelift" } ], - "time": "2024-02-10T11:10:03+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "dev-master", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c5ee33df86c06b3278c670f64273b1ba768a0744" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c5ee33df86c06b3278c670f64273b1ba768a0744", - "reference": "c5ee33df86c06b3278c670f64273b1ba768a0744", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -517,7 +516,6 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^9.0" }, - "default-branch": true, "bin": [ "bin/php-parse" ], @@ -548,9 +546,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/master" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-04-19T12:04:10+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", @@ -776,16 +774,16 @@ }, { "name": "phpbench/phpbench", - "version": "dev-master", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "c4af952ad3e19cc1a754b98f1ea47a10371e1749" + "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c4af952ad3e19cc1a754b98f1ea47a10371e1749", - "reference": "c4af952ad3e19cc1a754b98f1ea47a10371e1749", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", + "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", "shasum": "" }, "require": { @@ -808,10 +806,6 @@ "symfony/process": "^6.1 || ^7.0", "webmozart/glob": "^4.6" }, - "replace": { - "symfony/polyfill-php80": "*", - "symfony/polyfill-php81": "*" - }, "require-dev": { "dantleech/invoke": "^2.0", "ergebnis/composer-normalize": "^2.39", @@ -829,7 +823,6 @@ "suggest": { "ext-xdebug": "For Xdebug profiling extension." }, - "default-branch": true, "bin": [ "bin/phpbench" ], @@ -868,7 +861,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/master" + "source": "https://github.com/phpbench/phpbench/tree/1.3.1" }, "funding": [ { @@ -876,7 +869,7 @@ "type": "github" } ], - "time": "2024-04-10T12:50:15+00:00" + "time": "2024-06-30T11:04:37+00:00" }, { "name": "phpstan/phpstan", @@ -884,12 +877,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "3b03bac1068a585926a14e97692baef8642c2a1b" + "reference": "25658f615c8ca6d51b28da3e5c3e2b4ef47dd98e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3b03bac1068a585926a14e97692baef8642c2a1b", - "reference": "3b03bac1068a585926a14e97692baef8642c2a1b", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/25658f615c8ca6d51b28da3e5c3e2b4ef47dd98e", + "reference": "25658f615c8ca6d51b28da3e5c3e2b4ef47dd98e", "shasum": "" }, "require": { @@ -935,7 +928,7 @@ "type": "github" } ], - "time": "2024-04-22T13:39:03+00:00" + "time": "2024-07-04T11:58:23+00:00" }, { "name": "phpunit/php-code-coverage", @@ -943,12 +936,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "3352293d9e91513d5508c415835014881b420218" + "reference": "39d628812d8d83344a6c1b07799e3700d830d355" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/3352293d9e91513d5508c415835014881b420218", - "reference": "3352293d9e91513d5508c415835014881b420218", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/39d628812d8d83344a6c1b07799e3700d830d355", + "reference": "39d628812d8d83344a6c1b07799e3700d830d355", "shasum": "" }, "require": { @@ -967,7 +960,7 @@ "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -976,7 +969,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2-dev" } }, "autoload": { @@ -1013,7 +1006,7 @@ "type": "github" } ], - "time": "2024-03-22T05:16:32+00:00" + "time": "2024-06-29T07:23:05+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1262,12 +1255,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "33a0610878994fc134c74c25d5276d606d49079b" + "reference": "d229f5800280c68f1c5fc28b132bc64ff5ed3dd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33a0610878994fc134c74c25d5276d606d49079b", - "reference": "33a0610878994fc134c74c25d5276d606d49079b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d229f5800280c68f1c5fc28b132bc64ff5ed3dd4", + "reference": "d229f5800280c68f1c5fc28b132bc64ff5ed3dd4", "shasum": "" }, "require": { @@ -1357,7 +1350,7 @@ "type": "tidelift" } ], - "time": "2024-04-20T06:05:08+00:00" + "time": "2024-07-03T05:19:53+00:00" }, { "name": "psr/cache", @@ -2589,16 +2582,16 @@ }, { "name": "symfony/console", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1b84910b638ce3265e132d7b42405b2db64f6f69" + "reference": "b71a095124de660d598da3031c39e2790f64e28a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1b84910b638ce3265e132d7b42405b2db64f6f69", - "reference": "1b84910b638ce3265e132d7b42405b2db64f6f69", + "url": "https://api.github.com/repos/symfony/console/zipball/b71a095124de660d598da3031c39e2790f64e28a", + "reference": "b71a095124de660d598da3031c39e2790f64e28a", "shasum": "" }, "require": { @@ -2662,7 +2655,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/7.1" + "source": "https://github.com/symfony/console/tree/7.2" }, "funding": [ { @@ -2678,7 +2671,7 @@ "type": "tidelift" } ], - "time": "2024-04-06T17:55:56+00:00" + "time": "2024-06-28T10:04:05+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2686,12 +2679,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/2c438b99bb2753c1628c1e6f523991edea5b03a4", - "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -2730,7 +2723,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/main" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -2746,26 +2739,28 @@ "type": "tidelift" } ], - "time": "2024-01-02T14:07:37+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/filesystem", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "47d346741881ecf75f6b6474b52f0781e6c42af7" + "reference": "f655195171bc987675cb6557d7808d6c45823414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/47d346741881ecf75f6b6474b52f0781e6c42af7", - "reference": "47d346741881ecf75f6b6474b52f0781e6c42af7", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/f655195171bc987675cb6557d7808d6c45823414", + "reference": "f655195171bc987675cb6557d7808d6c45823414", "shasum": "" }, "require": { "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { "symfony/process": "^6.4|^7.0" }, "type": "library", @@ -2794,7 +2789,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/7.1" + "source": "https://github.com/symfony/filesystem/tree/7.2" }, "funding": [ { @@ -2810,20 +2805,20 @@ "type": "tidelift" } ], - "time": "2024-04-16T16:29:43+00:00" + "time": "2024-06-28T10:04:05+00:00" }, { "name": "symfony/finder", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03" + "reference": "7de31242fcdb19eef948b2ce465003e5b992a1c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03", - "reference": "9bfc6ffa24b1b66f7c3c9f71b2870e1413c1ce03", + "url": "https://api.github.com/repos/symfony/finder/zipball/7de31242fcdb19eef948b2ce465003e5b992a1c8", + "reference": "7de31242fcdb19eef948b2ce465003e5b992a1c8", "shasum": "" }, "require": { @@ -2858,7 +2853,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/7.1" + "source": "https://github.com/symfony/finder/tree/7.2" }, "funding": [ { @@ -2874,20 +2869,20 @@ "type": "tidelift" } ], - "time": "2024-03-20T15:26:56+00:00" + "time": "2024-06-24T16:01:36+00:00" }, { "name": "symfony/options-resolver", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce" + "reference": "f203cbd85dbb12960c7d47f021faa15fe8d010e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9564f64c16f99e29f252eafc642965e8fcb755ce", - "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/f203cbd85dbb12960c7d47f021faa15fe8d010e3", + "reference": "f203cbd85dbb12960c7d47f021faa15fe8d010e3", "shasum": "" }, "require": { @@ -2925,7 +2920,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/7.1" + "source": "https://github.com/symfony/options-resolver/tree/7.2" }, "funding": [ { @@ -2941,7 +2936,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-06-20T15:52:34+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2949,12 +2944,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe", - "reference": "c9e59dec962d38cf2e0e4c61c4a1a1312f4dd7fe", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -3005,7 +3000,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/1.x" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -3021,7 +3016,7 @@ "type": "tidelift" } ], - "time": "2024-04-19T06:31:17+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -3029,12 +3024,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "0a1df740cbb01859ce1bac85b0ad58ffe02f69b6" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/0a1df740cbb01859ce1bac85b0ad58ffe02f69b6", - "reference": "0a1df740cbb01859ce1bac85b0ad58ffe02f69b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -3084,7 +3079,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/1.x" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -3100,7 +3095,7 @@ "type": "tidelift" } ], - "time": "2024-04-19T06:31:17+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", @@ -3108,12 +3103,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "2a090dc3db090fcb35cc7329d18a07f281f15d79" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2a090dc3db090fcb35cc7329d18a07f281f15d79", - "reference": "2a090dc3db090fcb35cc7329d18a07f281f15d79", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -3166,7 +3161,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/1.x" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -3182,7 +3177,7 @@ "type": "tidelift" } ], - "time": "2024-04-19T06:31:17+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3190,12 +3185,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e642fbe7a7b73cdb05460555289a9057bfd6ead6" + "reference": "8740a072b86292957feb42703edde77fcfca84fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e642fbe7a7b73cdb05460555289a9057bfd6ead6", - "reference": "e642fbe7a7b73cdb05460555289a9057bfd6ead6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8740a072b86292957feb42703edde77fcfca84fb", + "reference": "8740a072b86292957feb42703edde77fcfca84fb", "shasum": "" }, "require": { @@ -3263,20 +3258,20 @@ "type": "tidelift" } ], - "time": "2024-04-19T06:31:17+00:00" + "time": "2024-06-20T08:18:00+00:00" }, { "name": "symfony/process", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "8e99b1b15d2975b242fc089382c8f8055a85d996" + "reference": "ca79b6e26d679b30022f9215319d4ea8b95ef5fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8e99b1b15d2975b242fc089382c8f8055a85d996", - "reference": "8e99b1b15d2975b242fc089382c8f8055a85d996", + "url": "https://api.github.com/repos/symfony/process/zipball/ca79b6e26d679b30022f9215319d4ea8b95ef5fe", + "reference": "ca79b6e26d679b30022f9215319d4ea8b95ef5fe", "shasum": "" }, "require": { @@ -3308,7 +3303,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/7.1" + "source": "https://github.com/symfony/process/tree/7.2" }, "funding": [ { @@ -3324,7 +3319,7 @@ "type": "tidelift" } ], - "time": "2024-04-05T09:28:19+00:00" + "time": "2024-06-27T12:22:56+00:00" }, { "name": "symfony/service-contracts", @@ -3332,12 +3327,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a17e69656265139c2ab4a62529f495a2a41fd6ce" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a17e69656265139c2ab4a62529f495a2a41fd6ce", - "reference": "a17e69656265139c2ab4a62529f495a2a41fd6ce", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { @@ -3392,7 +3387,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/main" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -3408,20 +3403,20 @@ "type": "tidelift" } ], - "time": "2024-04-05T09:39:30+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/string", - "version": "7.1.x-dev", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "236b450c00ab6560e6cda684853d2db3c6b41731" + "reference": "9e83b605d54359a762527bb2839c3031d0a08690" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/236b450c00ab6560e6cda684853d2db3c6b41731", - "reference": "236b450c00ab6560e6cda684853d2db3c6b41731", + "url": "https://api.github.com/repos/symfony/string/zipball/9e83b605d54359a762527bb2839c3031d0a08690", + "reference": "9e83b605d54359a762527bb2839c3031d0a08690", "shasum": "" }, "require": { @@ -3479,7 +3474,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/7.1" + "source": "https://github.com/symfony/string/tree/7.2" }, "funding": [ { @@ -3495,7 +3490,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-07-04T11:21:18+00:00" }, { "name": "theseer/tokenizer", diff --git a/src/Http/Http.php b/src/Http/Http.php index dbe8fd0e..05b61aaa 100755 --- a/src/Http/Http.php +++ b/src/Http/Http.php @@ -53,7 +53,7 @@ class Http extends Base * Http * * @param Adapter $server - * @param string $timezone + * @param string $timezone */ public function __construct(Adapter $server, Container $container, string $timezone) { @@ -84,7 +84,7 @@ public function setRequestClass(string $requestClass) * * Add GET request route * - * @param string $url + * @param string $url * @return Route */ public static function get(string $url): Route @@ -97,7 +97,7 @@ public static function get(string $url): Route * * Add POST request route * - * @param string $url + * @param string $url * @return Route */ public static function post(string $url): Route @@ -110,7 +110,7 @@ public static function post(string $url): Route * * Add PUT request route * - * @param string $url + * @param string $url * @return Route */ public static function put(string $url): Route @@ -123,7 +123,7 @@ public static function put(string $url): Route * * Add PATCH request route * - * @param string $url + * @param string $url * @return Route */ public static function patch(string $url): Route @@ -136,7 +136,7 @@ public static function patch(string $url): Route * * Add DELETE request route * - * @param string $url + * @param string $url * @return Route */ public static function delete(string $url): Route @@ -194,7 +194,7 @@ public static function getMode(): string * * Set current mode * - * @param string $value + * @param string $value * @return void */ public static function setMode(string $value): void @@ -229,7 +229,7 @@ public static function getAllowOverride(): bool * Set Allow override * * - * @param bool $value + * @param bool $value * @return void */ public static function setAllowOverride(bool $value): void @@ -242,8 +242,8 @@ public static function setAllowOverride(bool $value): void * * Add routing route method, path and callback * - * @param string $method - * @param string $url + * @param string $method + * @param string $url * @return Route */ public static function addRoute(string $method, string $url): Route @@ -258,12 +258,12 @@ public static function addRoute(string $method, string $url): Route /** * Load directory. * - * @param string $directory - * @param string|null $root + * @param string $directory + * @param string|null $root * @return void * * @throws \Exception - */ + */ public function loadFiles(string $directory, string $root = null): void { $this->files->load($directory, $root); @@ -272,7 +272,7 @@ public function loadFiles(string $directory, string $root = null): void /** * Is file loaded. * - * @param string $uri + * @param string $uri * @return bool */ protected function isFileLoaded(string $uri): bool @@ -283,7 +283,7 @@ protected function isFileLoaded(string $uri): bool /** * Get file contents. * - * @param string $uri + * @param string $uri * @return string * * @throws \Exception @@ -296,7 +296,7 @@ protected function getFileContents(string $uri): mixed /** * Get file MIME type. * - * @param string $uri + * @param string $uri * @return string * * @throws \Exception @@ -311,31 +311,25 @@ public function start() $this->server->onRequest(function ($request, $response) { $dependency = new Dependency(); - if(!\is_null($this->requestClass)) { + if (!\is_null($this->requestClass)) { $request = new $this->requestClass($request); } - if(!\is_null($this->responseClass)) { + if (!\is_null($this->responseClass)) { $response = new $this->responseClass($response); } $context = clone $this->container; - $context->set( - clone $dependency - ->setName('request') - ->setCallback(fn () => $request) - ) - ->set( - clone $dependency - ->setName('response') - ->setCallback(fn () => $response) - ) - ->set( - clone $dependency - ->setName('http') - ->setCallback(fn () => $this) - ); + $context->set(clone $dependency->setName('request')->setCallback(fn () => $request)) + ->set(clone $dependency->setName('response')->setCallback(fn () => $response)); + + // More base injection for GraphQL only + if($request->getUri() === '/v1/graphql') { + $context->set(clone $dependency->setName('http')->setCallback(fn () => $this)) + ->set(clone $dependency->setName('context')->setCallback(fn () => $context)); + } + $this->run($context); }); @@ -347,31 +341,28 @@ public function start() $container ->set( $dependency - ->setName('server') - ->setCallback(fn () => $this->server) - ) - ; + ->setName('server') + ->setCallback(fn () => $this->server) + ); try { foreach (self::$start as $hook) { $this->prepare($container, $hook, [], [])->inject($hook, true); } - } catch(\Exception $e) { - + } catch (\Exception $e) { $dependency = new Dependency(); $container->set( $dependency ->setName('error') ->setCallback(fn () => $e) - ) - ; + ); foreach (self::$errors as $error) { // Global error hooks if (in_array('*', $error->getGroups())) { try { $this->prepare($container, $error, [], [])->inject($error, true); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage() . ' on: ' . $e->getFile() . ':' . $e->getLine(), 500, $e); } } } @@ -386,7 +377,7 @@ public function start() * * Find matching route given current user request * - * @param Request $request + * @param Request $request * @return null|Route */ public function match(Request $request): ?Route @@ -401,14 +392,14 @@ public function match(Request $request): ?Route public function execute(Route $route, Request $request, Container $context): self { - return $this->lifecycle($route, $request, $context); + return $this->lifecycle($route, $request, $context); } /** * Execute a given route with middlewares and error handling * - * @param Route $route - * @param Request $request + * @param Route $route + * @param Request $request */ protected function lifecycle(Route $route, Request $request, Container $context): static { @@ -455,8 +446,7 @@ protected function lifecycle(Route $route, Request $request, Container $context) $dependency ->setName('error') ->setCallback(fn () => $e) - ) - ; + ); foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks @@ -464,7 +454,7 @@ protected function lifecycle(Route $route, Request $request, Container $context) try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { - throw new Exception('Group error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); + throw new Exception('Group error handler had an error: ' . $e->getMessage() . ' on: ' . $e->getFile() . ':' . $e->getLine(), 500, $e); } } } @@ -475,7 +465,7 @@ protected function lifecycle(Route $route, Request $request, Container $context) try { $this->prepare($context, $error, $pathValues, $request->getParams())->inject($error, true); } catch (\Throwable $e) { - throw new Exception('Global error handler had an error: ' . $e->getMessage(). ' on: ' . $e->getFile().':'.$e->getLine(), 500, $e); + throw new Exception('Global error handler had an error: ' . $e->getMessage() . ' on: ' . $e->getFile() . ':' . $e->getLine(), 500, $e); } } } @@ -496,8 +486,10 @@ protected function lifecycle(Route $route, Request $request, Container $context) */ public function run(Container $context): static { - $request = $context->get('request'); /** @var Request $request */ - $response = $context->get('response'); /** @var Response $response */ + $request = $context->get('request'); + /** @var Request $request */ + $response = $context->get('response'); + /** @var Response $response */ if ($this->isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache @@ -559,8 +551,7 @@ public function run(Container $context): static $dependency ->setName('error') ->setCallback(fn () => $e) - ) - ; + ); $this->prepare($context, $error, [], $request->getParams())->inject($error, true); } @@ -595,8 +586,7 @@ public function run(Container $context): static $dependency ->setName('error') ->setCallback(fn () => $e) - ) - ; + ); $this->prepare($context, $error, [], $request->getParams())->inject($error, true); } diff --git a/tests/HttpTest.php b/tests/HttpTest.php index eca9f871..70f41a27 100755 --- a/tests/HttpTest.php +++ b/tests/HttpTest.php @@ -39,8 +39,7 @@ public function setUp(): void $this->context ->set($request) - ->set($response) - ; + ->set($response); $this->http = new Http(new Server(), $this->context, 'Asia/Tel_Aviv'); @@ -105,7 +104,7 @@ public function testCanExecuteRoute(): void ->error() ->inject('error') ->action(function ($error) { - echo 'error: ' . $error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine(); + echo 'error: ' . $error->getMessage() . ' on file: ' . $error->getFile() . ' on line: ' . $error->getLine(); }); // Default Params @@ -129,8 +128,7 @@ public function testCanExecuteRoute(): void }); $context - ->set($request) - ; + ->set($request); \ob_start(); $this->http->run($context); @@ -163,8 +161,7 @@ public function testCanExecuteRouteWithParams(): void $context ->set($request) - ->set($rand) - ; + ->set($rand); $this->http ->error() @@ -236,8 +233,7 @@ public function testCanExecuteRouteWithParamsWithError(): void $context ->set($request) - ->set($rand) - ; + ->set($rand); $this->http->run($context); $result = \ob_get_contents(); @@ -341,8 +337,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void $context ->set($request) - ->set($rand) - ; + ->set($rand); $resource = $context->get('rand'); $this->http->run($context); @@ -372,8 +367,7 @@ public function testCanExecuteRouteWithParamsWithHooks(): void $context ->set($request) - ->set($rand) - ; + ->set($rand); $resource = $context->get('rand'); \ob_start(); @@ -419,14 +413,12 @@ public function testCanAddAndExecuteHooks() }); $context - ->set($request) - ; + ->set($request); \ob_start(); $this->http->run($context); $result = \ob_get_contents(); \ob_end_clean(); - $this->assertEquals('(init)-x-def-(shutdown)', $result); // Default Params @@ -457,7 +449,7 @@ public function testCanAddAndExecuteHooks() $result = \ob_get_contents(); \ob_end_clean(); - $this->assertEquals('(init)-x-def-(shutdown)', $result); + $this->assertEquals('x-def', $result); } public function testAllowRouteOverrides() @@ -533,8 +525,7 @@ public function testCanHookThrowExceptions() }); $context - ->set($request) - ; + ->set($request); \ob_start(); $this->http->run($context); @@ -556,8 +547,7 @@ public function testCanHookThrowExceptions() }); $context - ->set($request) - ; + ->set($request); \ob_start(); $this->http->run($context); @@ -650,8 +640,7 @@ public function testNoMismatchRoute(): void }); $context - ->set($request) - ; + ->set($request); $this->http->run($context); @@ -683,8 +672,7 @@ public function testCanRunRequest(): void }); $this->context - ->set($request) - ; + ->set($request); $this->http->run($context); $result = \ob_get_contents(); @@ -727,7 +715,7 @@ public function testWildcardRoute(): void ->inject('error') ->inject('response') ->action(function (Throwable $error, Response $response) { - $response->send($error->getMessage().' on file: '.$error->getFile().' on line: '.$error->getLine()); + $response->send($error->getMessage() . ' on file: ' . $error->getFile() . ' on line: ' . $error->getLine()); }); $context = clone $this->context; diff --git a/tests/e2e/ResponseSwooleCoroutineTest.php b/tests/e2e/ResponseSwooleCoroutineTest.php new file mode 100644 index 00000000..d1811e37 --- /dev/null +++ b/tests/e2e/ResponseSwooleCoroutineTest.php @@ -0,0 +1,17 @@ +client = new Client('http://swoole-coroutine'); + } +} From c27a91d11b6d89a2603ed929a5739c7bb9779d18 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:54:13 -0400 Subject: [PATCH 67/71] chore: merge and composer --- composer.lock | 492 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 324 insertions(+), 168 deletions(-) diff --git a/composer.lock b/composer.lock index 67cde3f0..35c83ca1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,154 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "33b8cf270cfbd8f86cbd1338d81f5140", - "packages": [], + "content-hash": "f961290f450cd8657302383ece07a86b", + "packages": [ + { + "name": "utopia-php/di", + "version": "dev-feat-framework-v2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/di.git", + "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/di/zipball/1fb7da5ead16de5d795ef10c1e22e39726eb6943", + "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25", + "swoole/ide-helper": "4.8.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/", + "Tests\\E2E\\": "tests/e2e" + } + }, + "scripts": { + "lint": [ + "vendor/bin/pint --test" + ], + "format": [ + "vendor/bin/pint" + ], + "check": [ + "vendor/bin/phpstan analyse -c phpstan.neon" + ], + "test": [ + "vendor/bin/phpunit --configuration phpunit.xml" + ] + }, + "license": [ + "MIT" + ], + "description": "A simple and lite library for managing dependency injections", + "keywords": [ + "framework", + "http", + "php", + "upf" + ], + "support": { + "source": "https://github.com/utopia-php/di/tree/feat-framework-v2", + "issues": "https://github.com/utopia-php/di/issues" + }, + "time": "2024-06-11T16:03:00+00:00" + }, + { + "name": "utopia-php/servers", + "version": "dev-dev", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/servers.git", + "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/4565c1c111f6da6b18bc0f00f350377a1e691e48", + "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "utopia-php/di": "dev-feat-framework-v2" + }, + "require-dev": { + "laravel/pint": "^0.2.3", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Servers\\": "src/Servers" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\E2E\\": "tests/Servers/Unit" + } + }, + "scripts": { + "test": [ + "phpunit" + ], + "analyse": [ + "vendor/bin/phpstan analyse" + ], + "format": [ + "vendor/bin/pint" + ], + "lint": [ + "vendor/bin/pint --test" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Team Appwrite", + "email": "team@appwrite.io" + } + ], + "description": "A base library for building Utopia style servers.", + "keywords": [ + "framework", + "php", + "servers", + "upf", + "utopia" + ], + "support": { + "source": "https://github.com/utopia-php/servers/tree/dev", + "issues": "https://github.com/utopia-php/servers/issues" + }, + "time": "2024-06-07T18:49:59+00:00" + } + ], "packages-dev": [ { "name": "doctrine/annotations", - "version": "2.0.1", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" + "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/94f40ad7ecbc6931958faa8a57c48dce5da2b468", + "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468", "shasum": "" }, "require": { @@ -38,6 +171,7 @@ "suggest": { "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -79,37 +213,38 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" + "source": "https://github.com/doctrine/annotations/tree/2.0.x" }, - "time": "2023-02-02T22:02:53+00:00" + "time": "2023-08-23T17:36:07+00:00" }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", + "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^12", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", "phpstan/phpstan": "^1.9.4", "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", + "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.4" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -135,7 +270,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.x" }, "funding": [ { @@ -151,20 +286,20 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2024-06-20T19:34:15+00:00" }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "3.1.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", + "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", "shasum": "" }, "require": { @@ -212,7 +347,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/3.1.x" }, "funding": [ { @@ -228,20 +363,20 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2024-02-05T12:02:27+00:00" }, { "name": "laravel/pint", - "version": "v1.16.1", + "version": "v1.16.2", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "9266a47f1b9231b83e0cfd849009547329d871b1" + "reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/9266a47f1b9231b83e0cfd849009547329d871b1", - "reference": "9266a47f1b9231b83e0cfd849009547329d871b1", + "url": "https://api.github.com/repos/laravel/pint/zipball/51f1ba679a6afe0315621ad143d788bd7ded0eca", + "reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca", "shasum": "" }, "require": { @@ -294,11 +429,11 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-06-18T16:50:05+00:00" + "time": "2024-07-09T15:58:08+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", @@ -323,6 +458,7 @@ "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, + "default-branch": true, "type": "library", "autoload": { "files": [ @@ -416,7 +552,7 @@ }, { "name": "phar-io/manifest", - "version": "2.0.4", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", @@ -436,6 +572,7 @@ "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -534,7 +671,7 @@ }, { "name": "phpbench/container", - "version": "2.2.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phpbench/container.git", @@ -555,6 +692,7 @@ "phpstan/phpstan": "^0.12.52", "phpunit/phpunit": "^8" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -735,16 +873,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.11.6", + "version": "1.12.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee" + "reference": "5263666d1bd1156e22931b7a5b0249c7b86882f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6ac78f1165346c83b4a753f7e4186d969c6ad0ee", - "reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5263666d1bd1156e22931b7a5b0249c7b86882f5", + "reference": "5263666d1bd1156e22931b7a5b0249c7b86882f5", "shasum": "" }, "require": { @@ -753,6 +891,7 @@ "conflict": { "phpstan/phpstan-shim": "*" }, + "default-branch": true, "bin": [ "phpstan", "phpstan.phar" @@ -789,20 +928,20 @@ "type": "github" } ], - "time": "2024-07-01T15:33:06+00:00" + "time": "2024-07-19T12:09:56+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "9.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "328a747f499cca790acff5634a4e55b957f40634" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/328a747f499cca790acff5634a4e55b957f40634", + "reference": "328a747f499cca790acff5634a4e55b957f40634", "shasum": "" }, "require": { @@ -821,7 +960,7 @@ "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -830,7 +969,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -859,7 +998,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2" }, "funding": [ { @@ -867,20 +1006,20 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-07-17T05:19:21+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/38b24367e1b340aa78b96d7cab042942d917bb84", + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84", "shasum": "" }, "require": { @@ -919,7 +1058,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0" }, "funding": [ { @@ -927,7 +1066,7 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2022-02-11T16:23:04+00:00" }, { "name": "phpunit/php-invoker", @@ -1112,45 +1251,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.19", + "version": "9.6.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + "reference": "79a254dbf969455359b8a1e2ca2a13eadc375fdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/79a254dbf969455359b8a1e2ca2a13eadc375fdd", + "reference": "79a254dbf969455359b8a1e2ca2a13eadc375fdd", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -1195,7 +1334,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6" }, "funding": [ { @@ -1211,29 +1350,33 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:35:58+00:00" + "time": "2024-07-17T05:44:44+00:00" }, { "name": "psr/cache", - "version": "3.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "url": "https://api.github.com/repos/php-fig/cache/zipball/0a7c67d0d1c8167b342eb74339d6f961663826ce", + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce", "shasum": "" }, "require": { "php": ">=8.0.0" }, + "suggest": { + "fig/cache-util": "Provides some useful PSR-6 utilities" + }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1258,27 +1401,28 @@ "psr-6" ], "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" + "source": "https://github.com/php-fig/cache/tree/master" }, - "time": "2021-02-03T23:26:27+00:00" + "time": "2021-02-24T03:25:37+00:00" }, { "name": "psr/container", - "version": "2.0.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "707984727bd5b2b670e59559d3ed2500240cf875" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875", "shasum": "" }, "require": { "php": ">=7.4.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1311,13 +1455,13 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2023-09-22T11:11:30+00:00" }, { "name": "psr/log", - "version": "3.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", @@ -1332,6 +1476,7 @@ "require": { "php": ">=8.0.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1367,7 +1512,7 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "1.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", @@ -1534,16 +1679,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b247957a1c8dc81a671770f74b479c0a78a818f1", + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1", "shasum": "" }, "require": { @@ -1596,7 +1741,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0" }, "funding": [ { @@ -1604,11 +1749,11 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2022-09-14T12:46:14+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", @@ -1665,7 +1810,7 @@ }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", @@ -1731,7 +1876,7 @@ }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "5.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", @@ -1782,7 +1927,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1" }, "funding": [ { @@ -1794,7 +1939,7 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", @@ -1871,7 +2016,7 @@ }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", @@ -1935,7 +2080,7 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "1.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", @@ -2104,7 +2249,7 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", @@ -2167,16 +2312,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.4", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", + "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", "shasum": "" }, "require": { @@ -2185,6 +2330,7 @@ "require-dev": { "phpunit/phpunit": "^9.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -2209,7 +2355,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/main" }, "funding": [ { @@ -2217,11 +2363,11 @@ "type": "github" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2024-03-14T18:47:08+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "3.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", @@ -2265,7 +2411,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/3.2" }, "funding": [ { @@ -2277,7 +2423,7 @@ }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", @@ -2330,23 +2476,23 @@ }, { "name": "seld/jsonlint", - "version": "1.10.2", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259" + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9bb7db07b5d66d90f6ebf542f09fc67d800e5259", - "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", "shasum": "" }, "require": { "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.5", + "phpstan/phpstan": "^1.11", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" }, "bin": [ @@ -2378,7 +2524,7 @@ ], "support": { "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.10.2" + "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" }, "funding": [ { @@ -2390,7 +2536,7 @@ "type": "tidelift" } ], - "time": "2024-02-07T12:57:50+00:00" + "time": "2024-07-11T14:55:45+00:00" }, { "name": "swoole/ide-helper", @@ -2436,16 +2582,16 @@ }, { "name": "symfony/console", - "version": "v7.1.2", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0aa29ca177f432ab68533432db0de059f39c92ae" + "reference": "22e3436515bb5719c77a502cfd8cd5972e09805c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0aa29ca177f432ab68533432db0de059f39c92ae", - "reference": "0aa29ca177f432ab68533432db0de059f39c92ae", + "url": "https://api.github.com/repos/symfony/console/zipball/22e3436515bb5719c77a502cfd8cd5972e09805c", + "reference": "22e3436515bb5719c77a502cfd8cd5972e09805c", "shasum": "" }, "require": { @@ -2509,7 +2655,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.2" + "source": "https://github.com/symfony/console/tree/7.2" }, "funding": [ { @@ -2525,11 +2671,11 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-07-19T06:45:40+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -2544,6 +2690,7 @@ "require": { "php": ">=8.1" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -2596,16 +2743,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.1.2", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + "reference": "bea731a0b0ae9e51a44d83a445db09fb89952d3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/bea731a0b0ae9e51a44d83a445db09fb89952d3a", + "reference": "bea731a0b0ae9e51a44d83a445db09fb89952d3a", "shasum": "" }, "require": { @@ -2642,7 +2789,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.2" + "source": "https://github.com/symfony/filesystem/tree/7.2" }, "funding": [ { @@ -2658,20 +2805,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-07-06T18:14:19+00:00" }, { "name": "symfony/finder", - "version": "v7.1.1", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6" + "reference": "f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fbb0ba67688b780efbc886c1a0a0948dcf7205d6", - "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "url": "https://api.github.com/repos/symfony/finder/zipball/f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9", + "reference": "f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9", "shasum": "" }, "require": { @@ -2706,7 +2853,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.1" + "source": "https://github.com/symfony/finder/tree/7.2" }, "funding": [ { @@ -2722,20 +2869,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-07-06T07:57:47+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.1", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" + "reference": "28b7840cd3a01a74bc86fa77587f02b351ad3ade" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", - "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/28b7840cd3a01a74bc86fa77587f02b351ad3ade", + "reference": "28b7840cd3a01a74bc86fa77587f02b351ad3ade", "shasum": "" }, "require": { @@ -2773,7 +2920,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" + "source": "https://github.com/symfony/options-resolver/tree/7.2" }, "funding": [ { @@ -2789,11 +2936,11 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-07-06T07:57:47+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2814,6 +2961,7 @@ "suggest": { "ext-ctype": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -2872,7 +3020,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -2890,6 +3038,7 @@ "suggest": { "ext-intl": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -2950,7 +3099,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -2968,6 +3117,7 @@ "suggest": { "ext-intl": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3031,16 +3181,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "1.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "8740a072b86292957feb42703edde77fcfca84fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8740a072b86292957feb42703edde77fcfca84fb", + "reference": "8740a072b86292957feb42703edde77fcfca84fb", "shasum": "" }, "require": { @@ -3052,6 +3202,7 @@ "suggest": { "ext-mbstring": "For best performance" }, + "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3091,7 +3242,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" }, "funding": [ { @@ -3107,20 +3258,20 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-06-20T08:18:00+00:00" }, { "name": "symfony/process", - "version": "v7.1.1", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" + "reference": "5c9cf89df869bb3522744a682272126134d3ea48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", - "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", + "url": "https://api.github.com/repos/symfony/process/zipball/5c9cf89df869bb3522744a682272126134d3ea48", + "reference": "5c9cf89df869bb3522744a682272126134d3ea48", "shasum": "" }, "require": { @@ -3152,7 +3303,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.1" + "source": "https://github.com/symfony/process/tree/7.2" }, "funding": [ { @@ -3168,11 +3319,11 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-07-06T07:57:47+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", @@ -3192,6 +3343,7 @@ "conflict": { "ext-psr": "<1.1|>=2" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -3255,16 +3407,16 @@ }, { "name": "symfony/string", - "version": "v7.1.2", + "version": "7.2.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8" + "reference": "04f7ef038c1b0a191c124e83928323264c8af401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/14221089ac66cf82e3cf3d1c1da65de305587ff8", - "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8", + "url": "https://api.github.com/repos/symfony/string/zipball/04f7ef038c1b0a191c124e83928323264c8af401", + "reference": "04f7ef038c1b0a191c124e83928323264c8af401", "shasum": "" }, "require": { @@ -3322,7 +3474,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.2" + "source": "https://github.com/symfony/string/tree/7.2" }, "funding": [ { @@ -3338,7 +3490,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:27:18+00:00" + "time": "2024-07-09T20:36:12+00:00" }, { "name": "theseer/tokenizer", @@ -3392,7 +3544,7 @@ }, { "name": "webmozart/glob", - "version": "4.7.0", + "version": "4.8.x-dev", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", @@ -3441,14 +3593,18 @@ } ], "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], + "minimum-stability": "dev", + "stability-flags": { + "utopia-php/servers": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.0", "ext-swoole": "*" }, - "platform-dev": [], + "platform-dev": { + "ext-xdebug": "*" + }, "plugin-api-version": "2.6.0" } From f355e93f363eabd6ba05fe870632d13ffc224123 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:00:28 -0400 Subject: [PATCH 68/71] Feat: Adding multiple from version 0.33 --- src/Http/Validator/Multiple.php | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/Http/Validator/Multiple.php diff --git a/src/Http/Validator/Multiple.php b/src/Http/Validator/Multiple.php new file mode 100644 index 00000000..4c919377 --- /dev/null +++ b/src/Http/Validator/Multiple.php @@ -0,0 +1,115 @@ +addRule($rule); + } + + $this->type = $type; + } + /** + * Add rule + * + * Add a new rule to the end of the rules containing array + * + * @param Validator $rule + * @return $this + */ + public function addRule(Validator $rule) + { + $this->rules[] = $rule; + + return $this; + } + + /** + * Get Description + * + * Returns validator description + * + * @return string + */ + public function getDescription(): string + { + $description = ''; + foreach ($this->rules as $key => $rule) { + $description .= ++$key . '. ' . $rule->getDescription() . " \n"; + } + + return $description; + } + + /** + * Is valid + * + * Validation will pass when all rules are valid if only one of the rules is invalid validation will fail. + * + * @param mixed $value + * @return bool + */ + public function isValid(mixed $value): bool + { + foreach ($this->rules as $rule) { /* @var $rule Validator */ + if (false === $rule->isValid($value)) { + return false; + } + } + + return true; + } + + /** + * Get Type + * + * Returns validator type. + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * Is array + * + * Function will return true if object is array. + * + * @return bool + */ + public function isArray(): bool + { + return true; + } +} From 530334e2fc406e142e3546f65cb35ff70938f6e6 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:36:50 -0400 Subject: [PATCH 69/71] chore: updating packages --- composer.json | 16 +-- composer.lock | 378 ++++++++++++++++++++++---------------------------- 2 files changed, 166 insertions(+), 228 deletions(-) diff --git a/composer.json b/composer.json index 9244c0a6..1d316c1c 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "upf" ], "license": "MIT", - "minimum-stability": "dev", + "minimum-stability": "stable", "autoload": { "psr-4": { "Utopia\\": "src/" @@ -30,7 +30,7 @@ "require": { "php": ">=8.0", "ext-swoole": "*", - "utopia-php/servers": "dev-dev" + "utopia-php/servers": "0.1.* " }, "require-dev": { "ext-xdebug": "*", @@ -39,15 +39,5 @@ "swoole/ide-helper": "4.8.3", "phpstan/phpstan": "^1.10", "phpbench/phpbench": "^1.2" - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/utopia-php/servers" - }, - { - "type": "vcs", - "url": "https://github.com/utopia-php/di" - } - ] + } } diff --git a/composer.lock b/composer.lock index 35c83ca1..fd7e5633 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f961290f450cd8657302383ece07a86b", + "content-hash": "cd780eab9403d28fc6a81d6e2063ae4c", "packages": [ { "name": "utopia-php/di", - "version": "dev-feat-framework-v2", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/di.git", - "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943" + "reference": "22490c95f7ac3898ed1c33f1b1b5dd577305ee31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/di/zipball/1fb7da5ead16de5d795ef10c1e22e39726eb6943", - "reference": "1fb7da5ead16de5d795ef10c1e22e39726eb6943", + "url": "https://api.github.com/repos/utopia-php/di/zipball/22490c95f7ac3898ed1c33f1b1b5dd577305ee31", + "reference": "22490c95f7ac3898ed1c33f1b1b5dd577305ee31", "shasum": "" }, "require": { @@ -37,20 +37,7 @@ "Tests\\E2E\\": "tests/e2e" } }, - "scripts": { - "lint": [ - "vendor/bin/pint --test" - ], - "format": [ - "vendor/bin/pint" - ], - "check": [ - "vendor/bin/phpstan analyse -c phpstan.neon" - ], - "test": [ - "vendor/bin/phpunit --configuration phpunit.xml" - ] - }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -62,28 +49,28 @@ "upf" ], "support": { - "source": "https://github.com/utopia-php/di/tree/feat-framework-v2", - "issues": "https://github.com/utopia-php/di/issues" + "issues": "https://github.com/utopia-php/di/issues", + "source": "https://github.com/utopia-php/di/tree/0.1.0" }, - "time": "2024-06-11T16:03:00+00:00" + "time": "2024-08-08T14:35:19+00:00" }, { "name": "utopia-php/servers", - "version": "dev-dev", + "version": "0.1.0", "source": { "type": "git", "url": "https://github.com/utopia-php/servers.git", - "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48" + "reference": "7d9e4f364fb1ab1889fb89ca96eb9946467cb09c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/servers/zipball/4565c1c111f6da6b18bc0f00f350377a1e691e48", - "reference": "4565c1c111f6da6b18bc0f00f350377a1e691e48", + "url": "https://api.github.com/repos/utopia-php/servers/zipball/7d9e4f364fb1ab1889fb89ca96eb9946467cb09c", + "reference": "7d9e4f364fb1ab1889fb89ca96eb9946467cb09c", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/di": "dev-feat-framework-v2" + "utopia-php/di": "0.1.*" }, "require-dev": { "laravel/pint": "^0.2.3", @@ -96,25 +83,7 @@ "Utopia\\Servers\\": "src/Servers" } }, - "autoload-dev": { - "psr-4": { - "Tests\\E2E\\": "tests/Servers/Unit" - } - }, - "scripts": { - "test": [ - "phpunit" - ], - "analyse": [ - "vendor/bin/phpstan analyse" - ], - "format": [ - "vendor/bin/pint" - ], - "lint": [ - "vendor/bin/pint --test" - ] - }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -133,25 +102,25 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/servers/tree/dev", - "issues": "https://github.com/utopia-php/servers/issues" + "issues": "https://github.com/utopia-php/servers/issues", + "source": "https://github.com/utopia-php/servers/tree/0.1.0" }, - "time": "2024-06-07T18:49:59+00:00" + "time": "2024-08-08T14:31:39+00:00" } ], "packages-dev": [ { "name": "doctrine/annotations", - "version": "2.0.x-dev", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468" + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/94f40ad7ecbc6931958faa8a57c48dce5da2b468", - "reference": "94f40ad7ecbc6931958faa8a57c48dce5da2b468", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", "shasum": "" }, "require": { @@ -171,7 +140,6 @@ "suggest": { "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -213,38 +181,37 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.x" + "source": "https://github.com/doctrine/annotations/tree/2.0.1" }, - "time": "2023-08-23T17:36:07+00:00" + "time": "2023-02-02T22:02:53+00:00" }, { "name": "doctrine/instantiator", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", - "reference": "0dfb69d79d0964b8a80bfa92c07f50e3e8d73542", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", "phpstan/phpstan": "^1.9.4", "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^10.5", + "phpunit/phpunit": "^9.5.27", "vimeo/psalm": "^5.4" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -270,7 +237,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.x" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -286,20 +253,20 @@ "type": "tidelift" } ], - "time": "2024-06-20T19:34:15+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "doctrine/lexer", - "version": "3.1.x-dev", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", - "reference": "cd03cc3c085aa94b046bd2d342b08d6b0e5d834f", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { @@ -347,7 +314,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.1.x" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -363,20 +330,20 @@ "type": "tidelift" } ], - "time": "2024-02-05T12:02:27+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "laravel/pint", - "version": "v1.16.2", + "version": "v1.17.2", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca" + "reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/51f1ba679a6afe0315621ad143d788bd7ded0eca", - "reference": "51f1ba679a6afe0315621ad143d788bd7ded0eca", + "url": "https://api.github.com/repos/laravel/pint/zipball/e8a88130a25e3f9d4d5785e6a1afca98268ab110", + "reference": "e8a88130a25e3f9d4d5785e6a1afca98268ab110", "shasum": "" }, "require": { @@ -387,13 +354,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.59.3", - "illuminate/view": "^10.48.12", - "larastan/larastan": "^2.9.7", + "friendsofphp/php-cs-fixer": "^3.61.1", + "illuminate/view": "^10.48.18", + "larastan/larastan": "^2.9.8", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.34.8" + "pestphp/pest": "^2.35.0" }, "bin": [ "builds/pint" @@ -429,11 +396,11 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-07-09T15:58:08+00:00" + "time": "2024-08-06T15:11:54+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.x-dev", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", @@ -458,7 +425,6 @@ "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, - "default-branch": true, "type": "library", "autoload": { "files": [ @@ -552,7 +518,7 @@ }, { "name": "phar-io/manifest", - "version": "dev-master", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", @@ -572,7 +538,6 @@ "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -671,7 +636,7 @@ }, { "name": "phpbench/container", - "version": "dev-master", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/phpbench/container.git", @@ -692,7 +657,6 @@ "phpstan/phpstan": "^0.12.52", "phpunit/phpunit": "^8" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -873,16 +837,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.x-dev", + "version": "1.11.10", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "5263666d1bd1156e22931b7a5b0249c7b86882f5" + "reference": "640410b32995914bde3eed26fa89552f9c2c082f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5263666d1bd1156e22931b7a5b0249c7b86882f5", - "reference": "5263666d1bd1156e22931b7a5b0249c7b86882f5", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f", + "reference": "640410b32995914bde3eed26fa89552f9c2c082f", "shasum": "" }, "require": { @@ -891,7 +855,6 @@ "conflict": { "phpstan/phpstan-shim": "*" }, - "default-branch": true, "bin": [ "phpstan", "phpstan.phar" @@ -928,20 +891,20 @@ "type": "github" } ], - "time": "2024-07-19T12:09:56+00:00" + "time": "2024-08-08T09:02:50+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.x-dev", + "version": "9.2.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "328a747f499cca790acff5634a4e55b957f40634" + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/328a747f499cca790acff5634a4e55b957f40634", - "reference": "328a747f499cca790acff5634a4e55b957f40634", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", "shasum": "" }, "require": { @@ -960,7 +923,7 @@ "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -969,7 +932,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-master": "9.2-dev" } }, "autoload": { @@ -998,7 +961,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" }, "funding": [ { @@ -1006,20 +969,20 @@ "type": "github" } ], - "time": "2024-07-17T05:19:21+00:00" + "time": "2024-03-02T06:37:42+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.x-dev", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "38b24367e1b340aa78b96d7cab042942d917bb84" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/38b24367e1b340aa78b96d7cab042942d917bb84", - "reference": "38b24367e1b340aa78b96d7cab042942d917bb84", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { @@ -1058,7 +1021,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -1066,7 +1029,7 @@ "type": "github" } ], - "time": "2022-02-11T16:23:04+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", @@ -1251,16 +1214,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.x-dev", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "79a254dbf969455359b8a1e2ca2a13eadc375fdd" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/79a254dbf969455359b8a1e2ca2a13eadc375fdd", - "reference": "79a254dbf969455359b8a1e2ca2a13eadc375fdd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { @@ -1334,7 +1297,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -1350,33 +1313,29 @@ "type": "tidelift" } ], - "time": "2024-07-17T05:44:44+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { "name": "psr/cache", - "version": "dev-master", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce" + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/0a7c67d0d1c8167b342eb74339d6f961663826ce", - "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", "shasum": "" }, "require": { "php": ">=8.0.0" }, - "suggest": { - "fig/cache-util": "Provides some useful PSR-6 utilities" - }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -1401,28 +1360,27 @@ "psr-6" ], "support": { - "source": "https://github.com/php-fig/cache/tree/master" + "source": "https://github.com/php-fig/cache/tree/3.0.0" }, - "time": "2021-02-24T03:25:37+00:00" + "time": "2021-02-03T23:26:27+00:00" }, { "name": "psr/container", - "version": "dev-master", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1455,13 +1413,13 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2023-09-22T11:11:30+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/log", - "version": "dev-master", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", @@ -1476,7 +1434,6 @@ "require": { "php": ">=8.0.0" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -1512,7 +1469,7 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.x-dev", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", @@ -1679,16 +1636,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.x-dev", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b247957a1c8dc81a671770f74b479c0a78a818f1", - "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -1741,7 +1698,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -1749,11 +1706,11 @@ "type": "github" } ], - "time": "2022-09-14T12:46:14+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.x-dev", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", @@ -1810,7 +1767,7 @@ }, { "name": "sebastian/diff", - "version": "4.0.x-dev", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", @@ -1876,7 +1833,7 @@ }, { "name": "sebastian/environment", - "version": "5.1.x-dev", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", @@ -1927,7 +1884,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -1939,7 +1896,7 @@ }, { "name": "sebastian/exporter", - "version": "4.0.x-dev", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", @@ -2016,7 +1973,7 @@ }, { "name": "sebastian/global-state", - "version": "5.0.x-dev", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", @@ -2080,7 +2037,7 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.x-dev", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", @@ -2249,7 +2206,7 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.x-dev", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", @@ -2312,16 +2269,16 @@ }, { "name": "sebastian/resource-operations", - "version": "dev-main", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", - "reference": "ff553e7482dcee39fa4acc2b175d6ddeb0f7bc25", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -2330,7 +2287,6 @@ "require-dev": { "phpunit/phpunit": "^9.0" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -2355,7 +2311,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/main" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -2363,11 +2319,11 @@ "type": "github" } ], - "time": "2024-03-14T18:47:08+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", - "version": "3.2.x-dev", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", @@ -2411,7 +2367,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -2423,7 +2379,7 @@ }, { "name": "sebastian/version", - "version": "3.0.x-dev", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", @@ -2582,16 +2538,16 @@ }, { "name": "symfony/console", - "version": "7.2.x-dev", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "22e3436515bb5719c77a502cfd8cd5972e09805c" + "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/22e3436515bb5719c77a502cfd8cd5972e09805c", - "reference": "22e3436515bb5719c77a502cfd8cd5972e09805c", + "url": "https://api.github.com/repos/symfony/console/zipball/cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", + "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", "shasum": "" }, "require": { @@ -2655,7 +2611,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/7.2" + "source": "https://github.com/symfony/console/tree/v7.1.3" }, "funding": [ { @@ -2671,11 +2627,11 @@ "type": "tidelift" } ], - "time": "2024-07-19T06:45:40+00:00" + "time": "2024-07-26T12:41:01+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "dev-main", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -2690,7 +2646,6 @@ "require": { "php": ">=8.1" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -2743,16 +2698,16 @@ }, { "name": "symfony/filesystem", - "version": "7.2.x-dev", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bea731a0b0ae9e51a44d83a445db09fb89952d3a" + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bea731a0b0ae9e51a44d83a445db09fb89952d3a", - "reference": "bea731a0b0ae9e51a44d83a445db09fb89952d3a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", "shasum": "" }, "require": { @@ -2789,7 +2744,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/7.2" + "source": "https://github.com/symfony/filesystem/tree/v7.1.2" }, "funding": [ { @@ -2805,20 +2760,20 @@ "type": "tidelift" } ], - "time": "2024-07-06T18:14:19+00:00" + "time": "2024-06-28T10:03:55+00:00" }, { "name": "symfony/finder", - "version": "7.2.x-dev", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9" + "reference": "717c6329886f32dc65e27461f80f2a465412fdca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9", - "reference": "f076e3c9d7ea8486d981aa477d5c7f18c6f44fa9", + "url": "https://api.github.com/repos/symfony/finder/zipball/717c6329886f32dc65e27461f80f2a465412fdca", + "reference": "717c6329886f32dc65e27461f80f2a465412fdca", "shasum": "" }, "require": { @@ -2853,7 +2808,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/7.2" + "source": "https://github.com/symfony/finder/tree/v7.1.3" }, "funding": [ { @@ -2869,20 +2824,20 @@ "type": "tidelift" } ], - "time": "2024-07-06T07:57:47+00:00" + "time": "2024-07-24T07:08:44+00:00" }, { "name": "symfony/options-resolver", - "version": "7.2.x-dev", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "28b7840cd3a01a74bc86fa77587f02b351ad3ade" + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/28b7840cd3a01a74bc86fa77587f02b351ad3ade", - "reference": "28b7840cd3a01a74bc86fa77587f02b351ad3ade", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", "shasum": "" }, "require": { @@ -2920,7 +2875,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/7.2" + "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" }, "funding": [ { @@ -2936,11 +2891,11 @@ "type": "tidelift" } ], - "time": "2024-07-06T07:57:47+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "1.x-dev", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2961,7 +2916,6 @@ "suggest": { "ext-ctype": "For best performance" }, - "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3020,7 +2974,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "1.x-dev", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -3038,7 +2992,6 @@ "suggest": { "ext-intl": "For best performance" }, - "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3099,7 +3052,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "1.x-dev", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -3117,7 +3070,6 @@ "suggest": { "ext-intl": "For best performance" }, - "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3181,16 +3133,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "1.x-dev", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8740a072b86292957feb42703edde77fcfca84fb" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8740a072b86292957feb42703edde77fcfca84fb", - "reference": "8740a072b86292957feb42703edde77fcfca84fb", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -3202,7 +3154,6 @@ "suggest": { "ext-mbstring": "For best performance" }, - "default-branch": true, "type": "library", "extra": { "thanks": { @@ -3242,7 +3193,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -3258,20 +3209,20 @@ "type": "tidelift" } ], - "time": "2024-06-20T08:18:00+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/process", - "version": "7.2.x-dev", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5c9cf89df869bb3522744a682272126134d3ea48" + "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5c9cf89df869bb3522744a682272126134d3ea48", - "reference": "5c9cf89df869bb3522744a682272126134d3ea48", + "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca", "shasum": "" }, "require": { @@ -3303,7 +3254,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/7.2" + "source": "https://github.com/symfony/process/tree/v7.1.3" }, "funding": [ { @@ -3319,11 +3270,11 @@ "type": "tidelift" } ], - "time": "2024-07-06T07:57:47+00:00" + "time": "2024-07-26T12:44:47+00:00" }, { "name": "symfony/service-contracts", - "version": "dev-main", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", @@ -3343,7 +3294,6 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { @@ -3407,16 +3357,16 @@ }, { "name": "symfony/string", - "version": "7.2.x-dev", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "04f7ef038c1b0a191c124e83928323264c8af401" + "reference": "ea272a882be7f20cad58d5d78c215001617b7f07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/04f7ef038c1b0a191c124e83928323264c8af401", - "reference": "04f7ef038c1b0a191c124e83928323264c8af401", + "url": "https://api.github.com/repos/symfony/string/zipball/ea272a882be7f20cad58d5d78c215001617b7f07", + "reference": "ea272a882be7f20cad58d5d78c215001617b7f07", "shasum": "" }, "require": { @@ -3474,7 +3424,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/7.2" + "source": "https://github.com/symfony/string/tree/v7.1.3" }, "funding": [ { @@ -3490,7 +3440,7 @@ "type": "tidelift" } ], - "time": "2024-07-09T20:36:12+00:00" + "time": "2024-07-22T10:25:37+00:00" }, { "name": "theseer/tokenizer", @@ -3544,7 +3494,7 @@ }, { "name": "webmozart/glob", - "version": "4.8.x-dev", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/webmozarts/glob.git", @@ -3593,10 +3543,8 @@ } ], "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "utopia-php/servers": 20 - }, + "minimum-stability": "stable", + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 2e14c32176b40d3294f715198226f7b60aaa2c2e Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:37:49 -0400 Subject: [PATCH 70/71] fix: fixing test --- .github/workflows/test.yml | 2 +- CONTRIBUTING.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca3b5885..a6f1e642 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: run: composer validate --strict - name: Setup Docker - run: docker-compose up -d --build + run: docker compose up -d --build - name: Wait for Server to be ready run: sleep 10 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ab8893b..361c6a7b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,9 +66,9 @@ $ git push origin [name_of_your_new_branch] ### Testing -- `docker-compose up -d` -- `docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml` -- `docker-compose exec web vendor/bin/psalm --show-info=true` +- `docker compose up -d` +- `docker compose exec web vendor/bin/phpunit --configuration phpunit.xml` +- `docker compose exec web vendor/bin/psalm --show-info=true` ## Introducing New Features From ee50ec949d51f8e12b80cf05a39973140ac05dd2 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:40:27 -0400 Subject: [PATCH 71/71] chore: cleanup --- src/Http/Adapter/Swoole/Server.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Http/Adapter/Swoole/Server.php b/src/Http/Adapter/Swoole/Server.php index 0724430f..0fc63b47 100755 --- a/src/Http/Adapter/Swoole/Server.php +++ b/src/Http/Adapter/Swoole/Server.php @@ -12,24 +12,10 @@ class Server extends Adapter public function __construct(string $host, string $port = null, array $settings = []) { - $workerNumber = swoole_cpu_num() * 6; $this->server = new SwooleServer($host, $port); $this->server->set(\array_merge($settings, [ 'open_http2_protocol' => true, - // 'http_compression' => true, - // 'http_compression_level' => 6, - - // Server - // 'log_level' => 0, 'dispatch_mode' => 2, - // 'worker_num' => $workerNumber, - // 'reactor_num' => swoole_cpu_num() * 2, - // 'task_worker_num' => $workerNumber, - // 'open_cpu_affinity' => true, - - // Coroutine - // 'enable_coroutine' => true, - // 'max_coroutine' => 1000, ])); }