diff --git a/Makefile b/Makefile index ea4baa64..f0b9a969 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,9 @@ tools/php-cs-fixer/vendor/bin/php-cs-fixer: tools/psalm/vendor/bin/psalm: $(MAKE) -C tools/psalm vendor +tools/psalm-phar/vendor/bin/psalm.phar: + $(MAKE) -C tools/psalm-phar vendor + vendor: composer.lock ${PHP_BIN} ${COMPOSER_BIN} install --no-interaction --prefer-dist --optimize-autoloader; touch vendor; @@ -154,8 +157,8 @@ prettier: node_modules "resources/{css,ts}/**/*.{js,css,ts,tsx}" .PHONY: psalm -psalm: tools/psalm/vendor/bin/psalm vendor - ./tools/psalm/vendor/bin/psalm \ +psalm: tools/psalm/vendor/bin/psalm tools/psalm-phar/vendor/bin/psalm.phar vendor + ./tools/psalm-phar/vendor/bin/psalm.phar \ --no-cache \ --show-info=true \ --root=$(CURDIR) diff --git a/README.md b/README.md index d58c7661..fc7cd7e9 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ advantage of the asynchronous environment. )] function Homepage(ServerRequestInterface $request, ResponseInterface $response): TwigTemplate { - return new TwigTemplate('website/homepage.twig'); + return new TwigTemplate($request, $response, 'website/homepage.twig'); } ``` diff --git a/composer.json b/composer.json index 361109ef..06686201 100644 --- a/composer.json +++ b/composer.json @@ -5,9 +5,6 @@ "license": "MIT", "autoload": { "files": [ - "src/helpers/coroutineMustGetContext.php", - "src/helpers/coroutineMustGo.php", - "src/helpers/coroutineMustRun.php", "src/helpers/generatorGetReturn.php" ], "psr-4": { @@ -64,7 +61,11 @@ "twig/twig": "^3.7", "webonyx/graphql-php": "^15.6", "beberlei/assert": "^3.3", - "dunglas/doctrine-json-odm": "^1.4" + "dunglas/doctrine-json-odm": "^1.4", + "amphp/amp": "^3.0", + "revolt/event-loop": "^1.0", + "amphp/http-server": "^3.3", + "amphp/http-server-form-parser": "^2.0" }, "require-dev": { "phpunit/phpunit": "^11.0", diff --git a/composer.lock b/composer.lock index 081003b3..041f6b8f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,1101 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f374222c5137b063b7090ec90f0f7334", + "content-hash": "307e8a0ba31f1031245ae08de75e7a5a", "packages": [ + { + "name": "amphp/amp", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/138801fb68cfc9c329da8a7b39d01ce7291ee4b0", + "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-05-10T21:37:46+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/daa00f2efdbd71565bf64ffefa89e37542addf93", + "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v2.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-02-17T04:49:38+00:00" + }, + { + "name": "amphp/cache", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Cache\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", + "support": { + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" + }, + { + "name": "amphp/dns", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/dns.git", + "reference": "04c88e67bef804203df934703bd422ea72f46b0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/dns/zipball/04c88e67bef804203df934703bd422ea72f46b0e", + "reference": "04c88e67bef804203df934703bd422ea72f46b0e", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/windows-registry": "^1.0.1", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Dns\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", + "keywords": [ + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" + ], + "support": { + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.1.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:49:29+00:00" + }, + { + "name": "amphp/hpack", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/hpack.git", + "reference": "4f293064b15682a2b178b1367ddf0b8b5feb0239" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/hpack/zipball/4f293064b15682a2b178b1367ddf0b8b5feb0239", + "reference": "4f293064b15682a2b178b1367ddf0b8b5feb0239", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "http2jp/hpack-test-case": "^1", + "nikic/php-fuzzer": "^0.0.10", + "phpunit/phpunit": "^7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "HTTP/2 HPack implementation.", + "homepage": "https://github.com/amphp/hpack", + "keywords": [ + "headers", + "hpack", + "http-2" + ], + "support": { + "issues": "https://github.com/amphp/hpack/issues", + "source": "https://github.com/amphp/hpack/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:00:16+00:00" + }, + { + "name": "amphp/http", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/http.git", + "reference": "fe6b4dd50c1e70caf823092398074b5082e1d6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/http/zipball/fe6b4dd50c1e70caf823092398074b5082e1d6da", + "reference": "fe6b4dd50c1e70caf823092398074b5082e1d6da", + "shasum": "" + }, + "require": { + "amphp/hpack": "^3", + "amphp/parser": "^1.1", + "league/uri-components": "^2.4.2 | ^7.1", + "php": ">=8.1", + "psr/http-message": "^1 | ^2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "league/uri": "^6.8 | ^7.1", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/constants.php" + ], + "psr-4": { + "Amp\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Basic HTTP primitives which can be shared by servers and clients.", + "support": { + "issues": "https://github.com/amphp/http/issues", + "source": "https://github.com/amphp/http/tree/v2.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-03T18:00:53+00:00" + }, + { + "name": "amphp/http-server", + "version": "v3.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/http-server.git", + "reference": "26001b1ffac11db30c627ed4daba2088951b0ffa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/http-server/zipball/26001b1ffac11db30c627ed4daba2088951b0ffa", + "reference": "26001b1ffac11db30c627ed4daba2088951b0ffa", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/hpack": "^3", + "amphp/http": "^2", + "amphp/pipeline": "^1", + "amphp/socket": "^2.1", + "amphp/sync": "^2", + "league/uri": "^6.8 | ^7.1", + "league/uri-interfaces": "^2.3 | ^7.1", + "php": ">=8.1", + "psr/http-message": "^1 | ^2", + "psr/log": "^1 | ^2 | ^3", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/http-client": "^5", + "amphp/log": "^2", + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "league/uri-components": "^2.4.2 | ^7.1", + "monolog/monolog": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "~5.23" + }, + "suggest": { + "ext-zlib": "Allows GZip compression of response bodies" + }, + "type": "library", + "autoload": { + "files": [ + "src/Driver/functions.php", + "src/Middleware/functions.php", + "src/functions.php" + ], + "psr-4": { + "Amp\\Http\\Server\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A non-blocking HTTP application server for PHP based on Amp.", + "homepage": "https://github.com/amphp/http-server", + "keywords": [ + "amp", + "amphp", + "async", + "http", + "non-blocking", + "server" + ], + "support": { + "issues": "https://github.com/amphp/http-server/issues", + "source": "https://github.com/amphp/http-server/tree/v3.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T15:46:46+00:00" + }, + { + "name": "amphp/http-server-form-parser", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/http-server-form-parser.git", + "reference": "6f160914a1cd9aaa104b589c0c590613600bfa70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/http-server-form-parser/zipball/6f160914a1cd9aaa104b589c0c590613600bfa70", + "reference": "6f160914a1cd9aaa104b589c0c590613600bfa70", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/http": "^2", + "amphp/http-server": "^3.2", + "amphp/pipeline": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/log": "^2", + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.6" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Http\\Server\\FormParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "An HTTP server plugin that simplifies form data handling. Effortlessly parse incoming form submissions and extracting its data.", + "homepage": "https://amphp.org/http-server-form-parser", + "keywords": [ + "amp", + "amphp", + "async", + "form", + "http", + "non-blocking", + "revolt" + ], + "support": { + "issues": "https://github.com/amphp/http-server-form-parser/issues", + "source": "https://github.com/amphp/http-server-form-parser/tree/v2.0.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2023-08-25T02:52:20+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/f1c2ce35d27ae86ead018adb803eccca7421dd9b", + "reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-10T14:48:16+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "375ef5b54a0d12c38e12728dde05a55e30f2fbec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/375ef5b54a0d12c38e12728dde05a55e30f2fbec", + "reference": "375ef5b54a0d12c38e12728dde05a55e30f2fbec", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.2.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-12T01:00:01+00:00" + }, + { + "name": "amphp/windows-registry", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/windows-registry.git", + "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/windows-registry/zipball/0d569e8f256cca974e3842b6e78b4e434bf98306", + "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306", + "shasum": "" + }, + "require": { + "amphp/byte-stream": "^2", + "amphp/process": "^2", + "php": ">=8.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\WindowsRegistry\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Windows Registry Reader.", + "support": { + "issues": "https://github.com/amphp/windows-registry/issues", + "source": "https://github.com/amphp/windows-registry/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-01-30T23:01:51+00:00" + }, { "name": "beberlei/assert", "version": "v3.3.2", @@ -75,25 +1168,25 @@ }, { "name": "brick/math", - "version": "0.11.0", + "version": "0.12.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", "shasum": "" }, "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^9.0", - "vimeo/psalm": "5.0.0" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" }, "type": "library", "autoload": { @@ -113,12 +1206,17 @@ "arithmetic", "bigdecimal", "bignum", + "bignumber", "brick", - "math" + "decimal", + "integer", + "math", + "mathematics", + "rational" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.11.0" + "source": "https://github.com/brick/math/tree/0.12.1" }, "funding": [ { @@ -126,7 +1224,51 @@ "type": "github" } ], - "time": "2023-01-15T23:15:59+00:00" + "time": "2023-11-29T23:19:16+00:00" + }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" }, { "name": "defuse/php-encryption", @@ -430,16 +1572,16 @@ }, { "name": "doctrine/dbal", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "9e588fe1f38a443cb17de6b86b803d9e028e2156" + "reference": "61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/9e588fe1f38a443cb17de6b86b803d9e028e2156", - "reference": "9e588fe1f38a443cb17de6b86b803d9e028e2156", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a", + "reference": "61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a", "shasum": "" }, "require": { @@ -518,7 +1660,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.0.1" + "source": "https://github.com/doctrine/dbal/tree/4.0.2" }, "funding": [ { @@ -534,7 +1676,7 @@ "type": "tidelift" } ], - "time": "2024-03-03T15:59:11+00:00" + "time": "2024-04-25T08:29:52+00:00" }, { "name": "doctrine/deprecations", @@ -585,16 +1727,16 @@ }, { "name": "doctrine/event-manager", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", "shasum": "" }, "require": { @@ -604,10 +1746,10 @@ "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^12", "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.28" + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" }, "type": "library", "autoload": { @@ -656,7 +1798,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.1" }, "funding": [ { @@ -672,7 +1814,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:59:15+00:00" + "time": "2024-05-22T20:47:39+00:00" }, { "name": "doctrine/inflector", @@ -1016,16 +2158,16 @@ }, { "name": "doctrine/orm", - "version": "3.1.2", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "f79d166a4e844beb9389f23bdb44abdbf58cec38" + "reference": "37946d3a21ddf837c0d84f8156ee60a92102e332" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/f79d166a4e844beb9389f23bdb44abdbf58cec38", - "reference": "f79d166a4e844beb9389f23bdb44abdbf58cec38", + "url": "https://api.github.com/repos/doctrine/orm/zipball/37946d3a21ddf837c0d84f8156ee60a92102e332", + "reference": "37946d3a21ddf837c0d84f8156ee60a92102e332", "shasum": "" }, "require": { @@ -1047,12 +2189,12 @@ "require-dev": { "doctrine/coding-standard": "^12.0", "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "1.10.59", + "phpstan/phpstan": "1.11.1", "phpunit/phpunit": "^10.4.0", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^5.4 || ^6.2 || ^7.0", - "vimeo/psalm": "5.22.2" + "vimeo/psalm": "5.24.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1098,9 +2240,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.1.2" + "source": "https://github.com/doctrine/orm/tree/3.2.0" }, - "time": "2024-04-15T14:20:40+00:00" + "time": "2024-05-23T14:27:52+00:00" }, { "name": "doctrine/persistence", @@ -1202,23 +2344,26 @@ }, { "name": "doctrine/sql-formatter", - "version": "1.2.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc" + "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc", - "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d1ac84aef745c69ea034929eb6d65a6908b675cc", + "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4" + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" }, "bin": [ "bin/sql-formatter" @@ -1248,9 +2393,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0" + "source": "https://github.com/doctrine/sql-formatter/tree/1.4.0" }, - "time": "2023-08-16T21:49:04+00:00" + "time": "2024-05-08T08:12:09+00:00" }, { "name": "dragonmantank/cron-expression", @@ -2057,21 +3202,23 @@ }, { "name": "hyperf/collection", - "version": "v3.1.19", + "version": "v3.1.23.2", "source": { "type": "git", "url": "https://github.com/hyperf/collection.git", - "reference": "fe9adae0fe88ec3330505c0cea758feee886d327" + "reference": "8d10ca88228ee47c9cee578ac3699e795f468ada" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/collection/zipball/fe9adae0fe88ec3330505c0cea758feee886d327", - "reference": "fe9adae0fe88ec3330505c0cea758feee886d327", + "url": "https://api.github.com/repos/hyperf/collection/zipball/8d10ca88228ee47c9cee578ac3699e795f468ada", + "reference": "8d10ca88228ee47c9cee578ac3699e795f468ada", "shasum": "" }, "require": { + "hyperf/conditionable": "~3.1.0", "hyperf/contract": "~3.1.0", "hyperf/macroable": "~3.1.0", + "hyperf/stringable": "~3.1.0", "php": ">=8.1" }, "type": "library", @@ -2116,7 +3263,7 @@ "type": "open_collective" } ], - "time": "2024-04-13T07:45:03+00:00" + "time": "2024-05-24T08:33:42+00:00" }, { "name": "hyperf/conditionable", @@ -2575,16 +3722,16 @@ }, { "name": "hyperf/grpc", - "version": "v3.1.15", + "version": "v3.1.21", "source": { "type": "git", "url": "https://github.com/hyperf/grpc.git", - "reference": "7b0424ce1b9af5016e2c8580d6de9eb9c6ec4bed" + "reference": "ea2b2ac9ee1382b1444393a42e676491d95f78e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/grpc/zipball/7b0424ce1b9af5016e2c8580d6de9eb9c6ec4bed", - "reference": "7b0424ce1b9af5016e2c8580d6de9eb9c6ec4bed", + "url": "https://api.github.com/repos/hyperf/grpc/zipball/ea2b2ac9ee1382b1444393a42e676491d95f78e0", + "reference": "ea2b2ac9ee1382b1444393a42e676491d95f78e0", "shasum": "" }, "require": { @@ -2634,20 +3781,20 @@ "type": "open_collective" } ], - "time": "2024-03-23T11:28:51+00:00" + "time": "2024-05-09T02:34:39+00:00" }, { "name": "hyperf/grpc-client", - "version": "v3.1.15", + "version": "v3.1.22", "source": { "type": "git", "url": "https://github.com/hyperf/grpc-client.git", - "reference": "4f8f1aeef090d7789020e87a058ed35dcf3fc127" + "reference": "93eaf2563f37a180da5202b6fa0d8230ef5b98db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/grpc-client/zipball/4f8f1aeef090d7789020e87a058ed35dcf3fc127", - "reference": "4f8f1aeef090d7789020e87a058ed35dcf3fc127", + "url": "https://api.github.com/repos/hyperf/grpc-client/zipball/93eaf2563f37a180da5202b6fa0d8230ef5b98db", + "reference": "93eaf2563f37a180da5202b6fa0d8230ef5b98db", "shasum": "" }, "require": { @@ -2661,7 +3808,7 @@ "php": ">=8.1" }, "suggest": { - "hyperf/load-balancer": "Use LoadBalancer for GrpcTransporter.(~3.0.0)" + "hyperf/load-balancer": "Use LoadBalancer for GrpcTransporter.(~3.1.0)" }, "type": "library", "extra": { @@ -2706,20 +3853,20 @@ "type": "open_collective" } ], - "time": "2024-03-23T11:28:51+00:00" + "time": "2024-05-15T06:42:24+00:00" }, { "name": "hyperf/macroable", - "version": "v3.1.15", + "version": "v3.1.23", "source": { "type": "git", "url": "https://github.com/hyperf/macroable.git", - "reference": "8912b5de69d25451b8ca103e4e47f0935e81072b" + "reference": "5f555c40bfec6aaab46f1bb1cac9ef556fbfbe72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/macroable/zipball/8912b5de69d25451b8ca103e4e47f0935e81072b", - "reference": "8912b5de69d25451b8ca103e4e47f0935e81072b", + "url": "https://api.github.com/repos/hyperf/macroable/zipball/5f555c40bfec6aaab46f1bb1cac9ef556fbfbe72", + "reference": "5f555c40bfec6aaab46f1bb1cac9ef556fbfbe72", "shasum": "" }, "require": { @@ -2764,7 +3911,7 @@ "type": "open_collective" } ], - "time": "2024-03-23T11:28:51+00:00" + "time": "2024-05-20T09:55:40+00:00" }, { "name": "hyperf/stdlib", @@ -2826,16 +3973,16 @@ }, { "name": "hyperf/stringable", - "version": "v3.1.17", + "version": "v3.1.20", "source": { "type": "git", "url": "https://github.com/hyperf/stringable.git", - "reference": "4997554ca2450c485446704adb9ed7c18ea93c70" + "reference": "71e5e5c2cb0cb4bb155805b581c93167211eb6b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hyperf/stringable/zipball/4997554ca2450c485446704adb9ed7c18ea93c70", - "reference": "4997554ca2450c485446704adb9ed7c18ea93c70", + "url": "https://api.github.com/repos/hyperf/stringable/zipball/71e5e5c2cb0cb4bb155805b581c93167211eb6b2", + "reference": "71e5e5c2cb0cb4bb155805b581c93167211eb6b2", "shasum": "" }, "require": { @@ -2893,7 +4040,7 @@ "type": "open_collective" } ], - "time": "2024-04-03T03:21:14+00:00" + "time": "2024-04-19T02:30:51+00:00" }, { "name": "hyperf/support", @@ -3085,6 +4232,64 @@ }, "time": "2024-03-08T09:58:59+00:00" }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Kelunik\\Certificate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Access certificate details and transform between different formats.", + "keywords": [ + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" + ], + "support": { + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" + }, + "time": "2023-02-03T21:26:53+00:00" + }, { "name": "lcobucci/clock", "version": "3.2.0", @@ -3712,6 +4917,88 @@ ], "time": "2024-03-23T07:42:40+00:00" }, + { + "name": "league/uri-components", + "version": "7.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-components.git", + "reference": "b94fe4097885f1b51c4c3fcb78025fbbabbb5d9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/b94fe4097885f1b51c4c3fcb78025fbbabbb5d9d", + "reference": "b94fe4097885f1b51c4c3fcb78025fbbabbb5d9d", + "shasum": "" + }, + "require": { + "league/uri": "^7.3", + "php": "^8.1" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "ext-mbstring": "to use the sorting algorithm of URLSearchParams", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI components manipulation library", + "homepage": "http://uri.thephpleague.com", + "keywords": [ + "authority", + "components", + "fragment", + "host", + "middleware", + "modifier", + "path", + "port", + "query", + "rfc3986", + "scheme", + "uri", + "url", + "userinfo" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-components/tree/7.4.1" + }, + "funding": [ + { + "url": "https://github.com/nyamsprod", + "type": "github" + } + ], + "time": "2024-03-23T07:42:40+00:00" + }, { "name": "league/uri-interfaces", "version": "7.4.1", @@ -3798,16 +5085,16 @@ }, { "name": "nette/php-generator", - "version": "v4.1.4", + "version": "v4.1.5", "source": { "type": "git", "url": "https://github.com/nette/php-generator.git", - "reference": "b135071d8da108445e4df2fc6a75522b23c0237d" + "reference": "690b00d81d42d5633e4457c43ef9754573b6f9d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/b135071d8da108445e4df2fc6a75522b23c0237d", - "reference": "b135071d8da108445e4df2fc6a75522b23c0237d", + "url": "https://api.github.com/repos/nette/php-generator/zipball/690b00d81d42d5633e4457c43ef9754573b6f9d6", + "reference": "690b00d81d42d5633e4457c43ef9754573b6f9d6", "shasum": "" }, "require": { @@ -3861,9 +5148,9 @@ ], "support": { "issues": "https://github.com/nette/php-generator/issues", - "source": "https://github.com/nette/php-generator/tree/v4.1.4" + "source": "https://github.com/nette/php-generator/tree/v4.1.5" }, - "time": "2024-03-07T23:06:26+00:00" + "time": "2024-05-12T17:31:02+00:00" }, { "name": "nette/schema", @@ -4515,20 +5802,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -4552,7 +5839,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -4564,9 +5851,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -4862,20 +6149,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.5", + "version": "4.7.6", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e" + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", - "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -4938,7 +6225,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.5" + "source": "https://github.com/ramsey/uuid/tree/4.7.6" }, "funding": [ { @@ -4950,20 +6237,92 @@ "type": "tidelift" } ], - "time": "2023-11-08T05:53:05+00:00" + "time": "2024-04-27T21:32:50+00:00" + }, + { + "name": "revolt/event-loop", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/25de49af7223ba039f64da4ae9a28ec2d10d0254", + "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + }, + "time": "2023-11-30T05:34:44+00:00" }, { "name": "symfony/cache", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b" + "reference": "48e3508338987d63b0114a00c208c4cbb76e5303" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/2d0d3f92c74c445410d05374908b03e0a1131e2b", - "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b", + "url": "https://api.github.com/repos/symfony/cache/zipball/48e3508338987d63b0114a00c208c4cbb76e5303", + "reference": "48e3508338987d63b0114a00c208c4cbb76e5303", "shasum": "" }, "require": { @@ -5030,7 +6389,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.0.6" + "source": "https://github.com/symfony/cache/tree/v7.0.7" }, "funding": [ { @@ -5046,20 +6405,20 @@ "type": "tidelift" } ], - "time": "2024-03-27T19:55:25+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.4.2", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "2c9db6509a1b21dad229606897639d3284f54b2a" + "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/2c9db6509a1b21dad229606897639d3284f54b2a", - "reference": "2c9db6509a1b21dad229606897639d3284f54b2a", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", "shasum": "" }, "require": { @@ -5069,7 +6428,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5106,7 +6465,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" }, "funding": [ { @@ -5122,20 +6481,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/clock", - "version": "v7.0.5", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2" + "reference": "2008671acb4a30b01c453de193cf9c80549ebda6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/8b9d08887353d627d5f6c3bf3373b398b49051c2", - "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2", + "url": "https://api.github.com/repos/symfony/clock/zipball/2008671acb4a30b01c453de193cf9c80549ebda6", + "reference": "2008671acb4a30b01c453de193cf9c80549ebda6", "shasum": "" }, "require": { @@ -5180,7 +6539,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.0.5" + "source": "https://github.com/symfony/clock/tree/v7.0.7" }, "funding": [ { @@ -5196,20 +6555,20 @@ "type": "tidelift" } ], - "time": "2024-03-02T12:46:12+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/console", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" + "reference": "c981e0e9380ce9f146416bde3150c79197ce9986" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "url": "https://api.github.com/repos/symfony/console/zipball/c981e0e9380ce9f146416bde3150c79197ce9986", + "reference": "c981e0e9380ce9f146416bde3150c79197ce9986", "shasum": "" }, "require": { @@ -5273,7 +6632,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.6" + "source": "https://github.com/symfony/console/tree/v7.0.7" }, "funding": [ { @@ -5289,20 +6648,20 @@ "type": "tidelift" } ], - "time": "2024-04-01T11:04:53+00:00" + "time": "2024-04-18T09:29:19+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": { @@ -5311,7 +6670,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5340,7 +6699,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": [ { @@ -5356,20 +6715,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "929527febf8e134eaba620de1f9396da1db0df85" + "reference": "da605530d1a75162359d494efc00f767f7fcd68a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/929527febf8e134eaba620de1f9396da1db0df85", - "reference": "929527febf8e134eaba620de1f9396da1db0df85", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/da605530d1a75162359d494efc00f767f7fcd68a", + "reference": "da605530d1a75162359d494efc00f767f7fcd68a", "shasum": "" }, "require": { @@ -5446,7 +6805,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.6" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.7" }, "funding": [ { @@ -5462,20 +6821,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T09:29:21+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e" + "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/834c28d533dd0636f910909d01b9ff45cc094b5e", - "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db2a7fab994d67d92356bb39c367db115d9d30f9", + "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9", "shasum": "" }, "require": { @@ -5526,7 +6885,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.7" }, "funding": [ { @@ -5542,20 +6901,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.2", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "4e64b49bf370ade88e567de29465762e316e4224" + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224", - "reference": "4e64b49bf370ade88e567de29465762e316e4224", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", "shasum": "" }, "require": { @@ -5565,7 +6924,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5602,7 +6961,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" }, "funding": [ { @@ -5618,20 +6977,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/expression-language", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "0877c599cb260c9614f9229c0a2090d6919fd621" + "reference": "b8ec919a6d3d47fc4e7845c256d164413207bf73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/0877c599cb260c9614f9229c0a2090d6919fd621", - "reference": "0877c599cb260c9614f9229c0a2090d6919fd621", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/b8ec919a6d3d47fc4e7845c256d164413207bf73", + "reference": "b8ec919a6d3d47fc4e7845c256d164413207bf73", "shasum": "" }, "require": { @@ -5665,7 +7024,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.0.3" + "source": "https://github.com/symfony/expression-language/tree/v7.0.7" }, "funding": [ { @@ -5681,26 +7040,27 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/filesystem", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d" + "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/cc168be6fbdcdf3401f50ae863ee3818ed4338f5", + "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5", "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": { @@ -5728,7 +7088,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/v7.0.7" }, "funding": [ { @@ -5744,20 +7104,20 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:37:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/finder", - "version": "v7.0.0", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" + "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "url": "https://api.github.com/repos/symfony/finder/zipball/4d58f0f4fe95a30d7b538d71197135483560b97c", + "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c", "shasum": "" }, "require": { @@ -5792,7 +7152,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.0.7" }, "funding": [ { @@ -5808,20 +7168,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:59:56+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/http-client", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858" + "reference": "6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/6e70473909f46fe5dd3b994a0f1b20ecb6b2f858", - "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858", + "url": "https://api.github.com/repos/symfony/http-client/zipball/6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7", + "reference": "6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7", "shasum": "" }, "require": { @@ -5884,7 +7244,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.0.6" + "source": "https://github.com/symfony/http-client/tree/v7.0.7" }, "funding": [ { @@ -5900,20 +7260,20 @@ "type": "tidelift" } ], - "time": "2024-04-01T20:49:44+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.4.2", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e" + "reference": "20414d96f391677bf80078aa55baece78b82647d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e", - "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", "shasum": "" }, "require": { @@ -5922,7 +7282,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5962,7 +7322,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" }, "funding": [ { @@ -5978,20 +7338,20 @@ "type": "tidelift" } ], - "time": "2024-04-01T18:51:09+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c" + "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8789625dcf36e5fbf753014678a1e090f1bc759c", - "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0194e064b8bdc29381462f790bab04e1cac8fdc8", + "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8", "shasum": "" }, "require": { @@ -6039,7 +7399,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.7" }, "funding": [ { @@ -6055,20 +7415,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:46:48+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/mailer", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0" + "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", - "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", + "url": "https://api.github.com/repos/symfony/mailer/zipball/4ff41a7c7998a88cfdc31b5841ef64d9246fc56a", + "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a", "shasum": "" }, "require": { @@ -6119,7 +7479,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.0.6" + "source": "https://github.com/symfony/mailer/tree/v7.0.7" }, "funding": [ { @@ -6135,20 +7495,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/messenger", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "4e281ef8bf5397be36fe14d64eb665fa12a945ad" + "reference": "90c217478f85d5289aae597551e2a4251e4d08c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/4e281ef8bf5397be36fe14d64eb665fa12a945ad", - "reference": "4e281ef8bf5397be36fe14d64eb665fa12a945ad", + "url": "https://api.github.com/repos/symfony/messenger/zipball/90c217478f85d5289aae597551e2a4251e4d08c3", + "reference": "90c217478f85d5289aae597551e2a4251e4d08c3", "shasum": "" }, "require": { @@ -6205,7 +7565,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.0.6" + "source": "https://github.com/symfony/messenger/tree/v7.0.7" }, "funding": [ { @@ -6221,20 +7581,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/mime", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2" + "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", - "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", + "url": "https://api.github.com/repos/symfony/mime/zipball/3adbf110c306546f6f00337f421d2edca0e8d3c0", + "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0", "shasum": "" }, "require": { @@ -6289,7 +7649,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.0.6" + "source": "https://github.com/symfony/mime/tree/v7.0.7" }, "funding": [ { @@ -6305,7 +7665,7 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:37:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7018,18 +8378,79 @@ ], "time": "2024-01-29T20:11:03+00:00" }, + { + "name": "symfony/process", + "version": "v7.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/3839e56b94dd1dbd13235d27504e66baf23faba0", + "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.0.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:29:19+00:00" + }, { "name": "symfony/property-access", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "1c268ba954ccc5e78cf035b391abb67759e24423" + "reference": "8661b861480d2807eb2789ff99d034c0c71ab955" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/1c268ba954ccc5e78cf035b391abb67759e24423", - "reference": "1c268ba954ccc5e78cf035b391abb67759e24423", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8661b861480d2807eb2789ff99d034c0c71ab955", + "reference": "8661b861480d2807eb2789ff99d034c0c71ab955", "shasum": "" }, "require": { @@ -7076,7 +8497,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.0.6" + "source": "https://github.com/symfony/property-access/tree/v7.0.7" }, "funding": [ { @@ -7092,20 +8513,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/property-info", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "b8844ddce7d53f78b57ec9be59da80fceddf3167" + "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/b8844ddce7d53f78b57ec9be59da80fceddf3167", - "reference": "b8844ddce7d53f78b57ec9be59da80fceddf3167", + "url": "https://api.github.com/repos/symfony/property-info/zipball/f0bdb46e19ab308527b324b7ec36161f6880a532", + "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532", "shasum": "" }, "require": { @@ -7159,7 +8580,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.0.6" + "source": "https://github.com/symfony/property-info/tree/v7.0.7" }, "funding": [ { @@ -7175,20 +8596,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/routing", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c" + "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/cded64e5bbf9f31786f1055fcc76718fdd77519c", - "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c", + "url": "https://api.github.com/repos/symfony/routing/zipball/9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b", + "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b", "shasum": "" }, "require": { @@ -7240,7 +8661,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.0.6" + "source": "https://github.com/symfony/routing/tree/v7.0.7" }, "funding": [ { @@ -7256,20 +8677,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T21:02:11+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/serializer", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "dbdc0c04c28ac53de1fa35f92fca26e9b1345d98" + "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/dbdc0c04c28ac53de1fa35f92fca26e9b1345d98", - "reference": "dbdc0c04c28ac53de1fa35f92fca26e9b1345d98", + "url": "https://api.github.com/repos/symfony/serializer/zipball/08f0c517acf4b12dfc0d3963cd12f7b8023aea31", + "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31", "shasum": "" }, "require": { @@ -7335,7 +8756,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.0.6" + "source": "https://github.com/symfony/serializer/tree/v7.0.7" }, "funding": [ { @@ -7351,25 +8772,26 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.2", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "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/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" @@ -7377,7 +8799,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -7417,7 +8839,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -7433,20 +8855,20 @@ "type": "tidelift" } ], - "time": "2023-12-19T21:51:00+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/stopwatch", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112" + "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/41a7a24aa1dc82adf46a06bc292d1923acfe6b84", + "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84", "shasum": "" }, "require": { @@ -7479,7 +8901,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.0.3" + "source": "https://github.com/symfony/stopwatch/tree/v7.0.7" }, "funding": [ { @@ -7495,20 +8917,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/string", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" + "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", + "url": "https://api.github.com/repos/symfony/string/zipball/e405b5424dc2528e02e31ba26b83a79fd4eb8f63", + "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63", "shasum": "" }, "require": { @@ -7565,7 +8987,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.4" + "source": "https://github.com/symfony/string/tree/v7.0.7" }, "funding": [ { @@ -7581,20 +9003,20 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:17:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/uid", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b" + "reference": "4f3a5d181999e25918586c8369de09e7814e7be2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/87cedaf3fabd7b733859d4d77aa4ca598259054b", - "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b", + "url": "https://api.github.com/repos/symfony/uid/zipball/4f3a5d181999e25918586c8369de09e7814e7be2", + "reference": "4f3a5d181999e25918586c8369de09e7814e7be2", "shasum": "" }, "require": { @@ -7639,7 +9061,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.0.3" + "source": "https://github.com/symfony/uid/tree/v7.0.7" }, "funding": [ { @@ -7655,20 +9077,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b" + "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c74c568d2a15a1d407cf40d61ea82bc2d521e27b", - "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/cdecc0022e40e90340ba1a59a3d5ccf069777078", + "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078", "shasum": "" }, "require": { @@ -7715,7 +9137,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.6" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.7" }, "funding": [ { @@ -7731,20 +9153,20 @@ "type": "tidelift" } ], - "time": "2024-03-20T21:25:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/yaml", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3" + "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c", + "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c", "shasum": "" }, "require": { @@ -7786,7 +9208,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.0.3" + "source": "https://github.com/symfony/yaml/tree/v7.0.7" }, "funding": [ { @@ -7802,20 +9224,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "twig/cache-extra", - "version": "v3.9.0", + "version": "v3.10.0", "source": { "type": "git", "url": "https://github.com/twigphp/cache-extra.git", - "reference": "317ec85c3831ef08003364acfa291c160f393e5d" + "reference": "7ffded2e8b466686436c0179dfaac6738ed1a113" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/cache-extra/zipball/317ec85c3831ef08003364acfa291c160f393e5d", - "reference": "317ec85c3831ef08003364acfa291c160f393e5d", + "url": "https://api.github.com/repos/twigphp/cache-extra/zipball/7ffded2e8b466686436c0179dfaac6738ed1a113", + "reference": "7ffded2e8b466686436c0179dfaac6738ed1a113", "shasum": "" }, "require": { @@ -7855,7 +9277,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/cache-extra/tree/v3.9.0" + "source": "https://github.com/twigphp/cache-extra/tree/v3.10.0" }, "funding": [ { @@ -7867,20 +9289,20 @@ "type": "tidelift" } ], - "time": "2024-02-10T08:52:03+00:00" + "time": "2024-05-11T07:35:57+00:00" }, { "name": "twig/twig", - "version": "v3.9.3", + "version": "v3.10.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58" + "reference": "67f29781ffafa520b0bbfbd8384674b42db04572" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", - "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/67f29781ffafa520b0bbfbd8384674b42db04572", + "reference": "67f29781ffafa520b0bbfbd8384674b42db04572", "shasum": "" }, "require": { @@ -7934,7 +9356,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.9.3" + "source": "https://github.com/twigphp/Twig/tree/v3.10.3" }, "funding": [ { @@ -7946,7 +9368,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T11:59:33+00:00" + "time": "2024-05-16T10:04:27+00:00" }, { "name": "webmozart/assert", @@ -8135,16 +9557,16 @@ }, { "name": "mockery/mockery", - "version": "1.6.11", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "81a161d0b135df89951abd52296adf97deb0723d" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d", - "reference": "81a161d0b135df89951abd52296adf97deb0723d", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { @@ -8214,7 +9636,7 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2024-03-21T18:34:15+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", @@ -8776,16 +10198,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.1.2", + "version": "11.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "51e342a0bc987e0ea8418105d0711f08ae116de3" + "reference": "d475be032238173ca3b0a516f5cc291d174708ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/51e342a0bc987e0ea8418105d0711f08ae116de3", - "reference": "51e342a0bc987e0ea8418105d0711f08ae116de3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d475be032238173ca3b0a516f5cc291d174708ae", + "reference": "d475be032238173ca3b0a516f5cc291d174708ae", "shasum": "" }, "require": { @@ -8856,7 +10278,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.1.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.1.3" }, "funding": [ { @@ -8872,7 +10294,7 @@ "type": "tidelift" } ], - "time": "2024-04-14T07:13:56+00:00" + "time": "2024-04-24T06:34:25+00:00" }, { "name": "sebastian/cli-parser", @@ -9831,16 +11253,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb" + "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", - "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d1627b66fd87c8b4d90cabe5671c29d575690924", + "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924", "shasum": "" }, "require": { @@ -9894,7 +11316,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.0.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.7" }, "funding": [ { @@ -9910,7 +11332,7 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "theseer/tokenizer", diff --git a/container.php b/container.php index 8febfa05..bfa2858c 100644 --- a/container.php +++ b/container.php @@ -7,12 +7,15 @@ defined('DM_ROOT') or exit('Configuration is not loaded.'); +use Distantmagic\Resonance\CoroutineDriver\Swoole; use Distantmagic\Resonance\DependencyInjectionContainer; -use Swoole\Runtime; -Runtime::enableCoroutine(SWOOLE_HOOK_ALL); +$coroutineDriver = new Swoole(); +$coroutineDriver->init(); -$container = new DependencyInjectionContainer(); +$container = new DependencyInjectionContainer( + coroutineDriver: $coroutineDriver, +); $container->phpProjectFiles->indexDirectory(DM_RESONANCE_ROOT); $container->phpProjectFiles->indexDirectory(DM_APP_ROOT); $container->registerSingletons(); diff --git a/docs/pages/docs/features/database/doctrine/entities.md b/docs/pages/docs/features/database/doctrine/entities.md index c07dbdd5..60fb5970 100644 --- a/docs/pages/docs/features/database/doctrine/entities.md +++ b/docs/pages/docs/features/database/doctrine/entities.md @@ -73,10 +73,17 @@ final readonly class BlogPostShow extends HttpController lookupField: 'slug', )] BlogPost $blogPost, + ResponseInterface $response, + ServerRequestInterface $request, ): HttpInterceptableInterface { - return new TwigTemplate('turbo/website/blog_post.twig', [ - 'blog_post' => $blogPost, - ]); + return new TwigTemplate( + $request, + $response, + 'turbo/website/blog_post.twig', + [ + 'blog_post' => $blogPost, + ], + ); } } ``` diff --git a/docs/pages/docs/features/database/doctrine/entity-managers.md b/docs/pages/docs/features/database/doctrine/entity-managers.md index 240acd6d..b4f391fa 100644 --- a/docs/pages/docs/features/database/doctrine/entity-managers.md +++ b/docs/pages/docs/features/database/doctrine/entity-managers.md @@ -114,9 +114,14 @@ final readonly class Blog extends HttpResponder $blogPostsRepository = $entityManager->getRepository(BlogPost::class); - return new TwigTemplate('turbo/website/blog.twig', [ - 'blog_posts' => $blogPostsRepository->findAll(), - ]); + return new TwigTemplate( + $request, + $response, + 'turbo/website/blog.twig', + [ + 'blog_posts' => $blogPostsRepository->findAll(), + ], + ); } } ``` @@ -148,6 +153,8 @@ use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\SingletonCollection; use Distantmagic\Resonance\TwigTemplate; use Doctrine\ORM\EntityRepository; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::GET, @@ -158,12 +165,19 @@ use Doctrine\ORM\EntityRepository; final readonly class Blog extends HttpController { public function createResponse( + ResponseInterface $response, + ServerRequestInterface $request, #[DoctrineEntityRepository(BlogPost::class)] EntityRepository $blogPosts, ): HttpInterceptableInterface { - return new TwigTemplate('website/blog.twig', [ - 'blog_posts' => $blogPosts->findAll(), - ]); + return new TwigTemplate( + $request, + $response, + 'website/blog.twig', + [ + 'blog_posts' => $blogPosts->findAll(), + ], + ); } } ``` diff --git a/docs/pages/docs/features/http/controllers.md b/docs/pages/docs/features/http/controllers.md index e1d0d296..1e537030 100644 --- a/docs/pages/docs/features/http/controllers.md +++ b/docs/pages/docs/features/http/controllers.md @@ -28,13 +28,6 @@ requests. The `respond` method is used internally for handling tasks like parameter binding, so you should not override it. -If you want to generate a new controller, you can do this manually, or you can -use the `generate:http-controller` command: - -```shell -$ php ./bin/resonance.php generate:http-controller Name -``` - ## Route Parameters ### Binding Route Parameters diff --git a/docs/pages/docs/features/http/middleware.md b/docs/pages/docs/features/http/middleware.md index cd712379..c86de82b 100644 --- a/docs/pages/docs/features/http/middleware.md +++ b/docs/pages/docs/features/http/middleware.md @@ -100,7 +100,7 @@ final readonly class BlogPostDestroy extends HttpController ): HttpInterceptableInterface { // ... - return new InternalRedirect(HttpRouteSymbol::Blog); + return new InternalRedirect($request, $response, HttpRouteSymbol::Blog); } } diff --git a/docs/pages/docs/features/http/responders.md b/docs/pages/docs/features/http/responders.md index 49677030..cb1dab90 100644 --- a/docs/pages/docs/features/http/responders.md +++ b/docs/pages/docs/features/http/responders.md @@ -36,13 +36,6 @@ HTTP Responder should be a `readonly` class that serves a single purpose Responders must implement the `respond` method that sends the response back to the HTTP client or forwards the request to a different responder. -You can generate a new responder class manually, or you can use the -`generate:http-responder` command: - -```shell -$ php ./bin/resonance.php generate:http-responder Name -``` - ## Responding to HTTP Requests To respond to requests you should use Swoole's `Response` object: @@ -136,14 +129,19 @@ namespace App\HttpResponder; use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\TwigTemplate; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::GET, pattern: '/blog', )] -function Blog(): TwigTemplate +function Blog( + ServerRequestInterface $request, + ResponseInterface $response, +): TwigTemplate { - return new TwigTemplate('turbo/blog.twig'); + return new TwigTemplate($request, $response, 'turbo/blog.twig'); } ``` diff --git a/docs/pages/docs/features/observability/observable-task-table/index.md b/docs/pages/docs/features/observability/observable-task-table/index.md index 79ffb342..efddfdc4 100644 --- a/docs/pages/docs/features/observability/observable-task-table/index.md +++ b/docs/pages/docs/features/observability/observable-task-table/index.md @@ -60,9 +60,14 @@ final readonly class ObservableTasksDashboard extends HttpResponder public function respond(ServerRequestInterface $request, ResponseInterface $response): HttpInterceptableInterface { - return new TwigTemplate('observable_task_table.twig',[ - 'observableTaskTable' => $this->observableTaskTable, - ]); + return new TwigTemplate( + $request, + $response, + 'observable_task_table.twig', + [ + 'observableTaskTable' => $this->observableTaskTable, + ] + ); } } ``` diff --git a/docs/pages/docs/features/security/authentication/index.md b/docs/pages/docs/features/security/authentication/index.md index 62d29d4b..173b9954 100644 --- a/docs/pages/docs/features/security/authentication/index.md +++ b/docs/pages/docs/features/security/authentication/index.md @@ -65,7 +65,7 @@ final readonly class LoginValidation extends HttpController $user, ); - return new InternalRedirect(HttpRouteSymbol::Homepage); + return new InternalRedirect($request, $response, HttpRouteSymbol::Homepage); } } ``` diff --git a/docs/pages/docs/features/templating/twig/rendering-templates.md b/docs/pages/docs/features/templating/twig/rendering-templates.md index ac0bd6e3..f8c0958a 100644 --- a/docs/pages/docs/features/templating/twig/rendering-templates.md +++ b/docs/pages/docs/features/templating/twig/rendering-templates.md @@ -40,7 +40,7 @@ final readonly class Twig extends HttpResponder { public function respond(ServerRequestInterface $request, ResponseInterface $response): HttpInterceptableInterface { - return new TwigTemplate('test.twig'); + return new TwigTemplate($request, $response, 'test.twig'); } } ``` diff --git a/docs/pages/docs/getting-started/installation-and-requirements.md b/docs/pages/docs/getting-started/installation-and-requirements.md index ed3b3e6a..bfece5db 100644 --- a/docs/pages/docs/getting-started/installation-and-requirements.md +++ b/docs/pages/docs/getting-started/installation-and-requirements.md @@ -91,9 +91,6 @@ Available commands: completion Dump the shell completion script help Display help for a command list List commands - generate - generate:http-controller Generate http-controller - generate:http-responder Generate http-responder static-pages static-pages:build Generate static pages ``` diff --git a/docs/pages/index.md b/docs/pages/index.md index 6445c247..a0356dbe 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -234,7 +234,7 @@ description: > )] function Homepage(ServerRequestInterface $request, ResponseInterface $response): TwigTemplate { - return new TwigTemplate('website/homepage.twig'); + return new TwigTemplate($request, $response, 'website/homepage.twig'); }
  • diff --git a/docs/pages/tutorials/hello-world/index.md b/docs/pages/tutorials/hello-world/index.md index 5420ee70..ff3fd32e 100644 --- a/docs/pages/tutorials/hello-world/index.md +++ b/docs/pages/tutorials/hello-world/index.md @@ -99,13 +99,18 @@ use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\HttpInterceptableInterface; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\TwigTemplate; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::GET, pattern: '/', routeSymbol: HttpRouteSymbol::Homepage, )] -function Homepage(): HttpInterceptableInterface +function Homepage( + ServerRequestInterface $request, + ResponseInterface $response, +): HttpInterceptableInterface { return new TwigTemplate('homepage.twig'); } diff --git a/docs/pages/tutorials/how-to-create-llm-websocket-chat-with-llama-cpp/index.md b/docs/pages/tutorials/how-to-create-llm-websocket-chat-with-llama-cpp/index.md index e5eebdf8..81406a4d 100644 --- a/docs/pages/tutorials/how-to-create-llm-websocket-chat-with-llama-cpp/index.md +++ b/docs/pages/tutorials/how-to-create-llm-websocket-chat-with-llama-cpp/index.md @@ -113,7 +113,7 @@ final readonly class LlmChat extends HttpResponder { public function respond(ServerRequestInterface $request, ResponseInterface $response): HttpInterceptableInterface { - return new TwigTemplate('turbo/llmchat/index.twig'); + return new TwigTemplate($request, $response, 'turbo/llmchat/index.twig'); } } ``` diff --git a/docs/pages/tutorials/session-based-authentication/index.md b/docs/pages/tutorials/session-based-authentication/index.md index 7d39a15f..1f5e27d0 100644 --- a/docs/pages/tutorials/session-based-authentication/index.md +++ b/docs/pages/tutorials/session-based-authentication/index.md @@ -239,15 +239,20 @@ use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\HttpInterceptableInterface; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\TwigTemplate; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::GET, pattern: '/login', routeSymbol: HttpRouteSymbol::LoginForm, )] -function LoginForm(): HttpInterceptableInterface +function LoginForm( + ServerRequestInterface $request, + ResponseInterface $response, +): HttpInterceptableInterface { - return new TwigTemplate('auth/login_form.twig'); + return new TwigTemplate($request, $response, 'auth/login_form.twig'); } ``` @@ -464,7 +469,7 @@ final readonly class LoginValidation extends HttpController $user->user, ); - return new InternalRedirect(HttpRouteSymbol::Homepage); + return new InternalRedirect($request, $response, HttpRouteSymbol::Homepage); } } ``` diff --git a/src/AmpServer.php b/src/AmpServer.php new file mode 100644 index 00000000..673fc883 --- /dev/null +++ b/src/AmpServer.php @@ -0,0 +1,63 @@ +server = SocketHttpServer::createForDirectAccess($logger); + $this->server->expose(sprintf( + '%s:%d', + $swooleConfiguration->host, + $swooleConfiguration->port, + )); + } + + public function __destruct() {} + + public function handleRequest(Request $request): Response + { + $request = new AmpServerRequest($request); + + return $this->psrAmpResponder->respondWithPsrResponse( + request: $request, + response: $this->httpResponderAggregate->respondToPsrRequest( + request: $request, + response: new ServerResponse(), + ), + ); + } + + public function start(): bool + { + $this->server->start($this, new DefaultErrorHandler()); + + trapSignal([SIGINT, SIGTERM]); + + $this->server->stop(); + + return true; + } +} diff --git a/src/Command/Cron.php b/src/Command/Cron.php index 28f7bca5..9eccda53 100644 --- a/src/Command/Cron.php +++ b/src/Command/Cron.php @@ -7,11 +7,10 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\CronJobAggregate; -use Distantmagic\Resonance\SwooleConfiguration; use Distantmagic\Resonance\TickTimerScheduler; use Psr\Log\LoggerInterface; -use Swoole\Event; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -22,12 +21,12 @@ final class Cron extends CoroutineCommand { public function __construct( + private readonly CoroutineDriverInterface $coroutineDriver, private readonly CronJobAggregate $cronJobAggregate, private readonly LoggerInterface $logger, - SwooleConfiguration $swooleConfiguration, private readonly TickTimerScheduler $tickTimerScheduler, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function executeInCoroutine(InputInterface $input, OutputInterface $output): int @@ -39,8 +38,7 @@ protected function executeInCoroutine(InputInterface $input, OutputInterface $ou } $this->tickTimerScheduler->start(); - - Event::wait(); + $this->coroutineDriver->wait(); return Command::SUCCESS; } diff --git a/src/Command/GenerateHttpController.php b/src/Command/GenerateHttpController.php deleted file mode 100644 index 4961f132..00000000 --- a/src/Command/GenerateHttpController.php +++ /dev/null @@ -1,104 +0,0 @@ -addArgument('class_name', InputArgument::REQUIRED); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $className = $input->getArgument('class_name'); - - if (!is_string($className)) { - $output->writeln('class_name is not a string'); - - return Command::FAILURE; - } - - $outputFilename = DM_APP_ROOT.'/HttpResponder/'.$className.'.php'; - - if (file_exists($outputFilename)) { - $output->writeln(sprintf('File already exists: %s', $outputFilename)); - - return Command::FAILURE; - } - - $classCode = $this->generateHttpResponderCode($className); - - file_put_contents($outputFilename, $classCode); - - $output->writeln(sprintf('Controller successfully created: %s', $outputFilename)); - - return Command::SUCCESS; - } - - private function generateHttpResponderCode(string $className): string - { - $phpFile = new PhpFile(); - $phpFile->setStrictTypes(); - - $namespace = $phpFile->addNamespace('App\\HttpResponder'); - $namespace->addUse(HttpInterceptableInterface::class); - $namespace->addUse(HttpController::class); - $namespace->addUse(HttpResponderInterface::class); - $namespace->addUse(Request::class); - $namespace->addUse(Response::class); - $namespace->addUse(Singleton::class); - $namespace->addUse(SingletonCollection::class); - - $class = $namespace->addClass($className); - $class->addAttribute(Singleton::class, [ - 'collection' => new Literal('SingletonCollection::HttpResponder'), - ]); - $class->setExtends(HttpController::class); - $class->setFinal(true); - $class->setReadOnly(true); - - $method = $class->addMethod(HttpController::MAGIC_METHOD_RESPOND); - $method->setReturnType(implode('|', [ - 'null', - HttpInterceptableInterface::class, - HttpResponderInterface::class, - ])); - $method->addParameter('request')->setType(Request::class); - $method->addParameter('response')->setType(Response::class); - $method->setBody(<<<'CODE' - $response->end('Hello, Resonance!'); - - return null; - CODE); - - return $this->printer->printFile($phpFile); - } -} diff --git a/src/Command/GenerateHttpResponder.php b/src/Command/GenerateHttpResponder.php deleted file mode 100644 index 726f292d..00000000 --- a/src/Command/GenerateHttpResponder.php +++ /dev/null @@ -1,103 +0,0 @@ -addArgument('class_name', InputArgument::REQUIRED); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $className = $input->getArgument('class_name'); - - if (!is_string($className)) { - $output->writeln('class_name is not a string'); - - return Command::FAILURE; - } - - $outputFilename = DM_APP_ROOT.'/HttpResponder/'.$className.'.php'; - - if (file_exists($outputFilename)) { - - return Command::FAILURE; - } - - $classCode = $this->generateHttpResponderCode($className); - - file_put_contents($outputFilename, $classCode); - - $output->writeln(sprintf('Responder successfully created: %s', $outputFilename)); - - return Command::SUCCESS; - } - - private function generateHttpResponderCode(string $className): string - { - $phpFile = new PhpFile(); - $phpFile->setStrictTypes(); - - $namespace = $phpFile->addNamespace('App\\HttpResponder'); - $namespace->addUse(HttpInterceptableInterface::class); - $namespace->addUse(HttpResponder::class); - $namespace->addUse(HttpResponderInterface::class); - $namespace->addUse(Request::class); - $namespace->addUse(Response::class); - $namespace->addUse(Singleton::class); - $namespace->addUse(SingletonCollection::class); - - $class = $namespace->addClass($className); - $class->addAttribute(Singleton::class, [ - 'collection' => new Literal('SingletonCollection::HttpResponder'), - ]); - $class->setExtends(HttpResponder::class); - $class->setFinal(true); - $class->setReadOnly(true); - - $method = $class->addMethod('respond'); - $method->setReturnType(implode('|', [ - 'null', - HttpInterceptableInterface::class, - HttpResponderInterface::class, - ])); - $method->addParameter('request')->setType(Request::class); - $method->addParameter('response')->setType(Response::class); - $method->setBody(<<<'CODE' - $response->end('Hello, Resonance!'); - - return null; - CODE); - - return $this->printer->printFile($phpFile); - } -} diff --git a/src/Command/GrpcGenerate.php b/src/Command/GrpcGenerate.php index c3fdd982..afb96466 100644 --- a/src/Command/GrpcGenerate.php +++ b/src/Command/GrpcGenerate.php @@ -8,8 +8,8 @@ use Distantmagic\Resonance\Attribute\RequiresPhpExtension; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\GrpcConfiguration; -use Distantmagic\Resonance\SwooleConfiguration; use RuntimeException; use Swoole\Coroutine\System; use Symfony\Component\Console\Input\InputInterface; @@ -26,11 +26,11 @@ final class GrpcGenerate extends CoroutineCommand { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly Filesystem $filesystem, private readonly GrpcConfiguration $grpcConfiguration, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function configure(): void {} diff --git a/src/Command/GrpcRewrite.php b/src/Command/GrpcRewrite.php index 87bc4d1e..5aa9e609 100644 --- a/src/Command/GrpcRewrite.php +++ b/src/Command/GrpcRewrite.php @@ -10,6 +10,7 @@ use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\Feature; use Distantmagic\Resonance\GrpcBaseClient; use Distantmagic\Resonance\GrpcConfiguration; @@ -17,7 +18,6 @@ use Distantmagic\Resonance\PHPFileIterator; use Distantmagic\Resonance\PHPFileReflectionClassIterator; use Distantmagic\Resonance\SingletonCollection; -use Distantmagic\Resonance\SwooleConfiguration; use Grpc\BaseStub; use Nette\PhpGenerator\ClassType; use Nette\PhpGenerator\PhpFile; @@ -36,12 +36,12 @@ final class GrpcRewrite extends CoroutineCommand { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly Filesystem $filesystem, private readonly GrpcConfiguration $grpcConfiguration, private readonly Printer $printer, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function configure(): void {} diff --git a/src/Command/LlamaCppGenerate.php b/src/Command/LlamaCppGenerate.php index fe2468ee..48169abb 100644 --- a/src/Command/LlamaCppGenerate.php +++ b/src/Command/LlamaCppGenerate.php @@ -5,8 +5,8 @@ namespace Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\LlamaCppClientInterface; -use Distantmagic\Resonance\SwooleConfiguration; use RuntimeException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -20,10 +20,10 @@ abstract class LlamaCppGenerate extends CoroutineCommand abstract protected function executeLlamaCppCommand(InputInterface $input, OutputInterface $output, string $prompt): int; public function __construct( + CoroutineDriverInterface $coroutineDriver, protected LlamaCppClientInterface $llamaCppClient, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function configure(): void diff --git a/src/Command/LlamaCppGenerate/Embedding.php b/src/Command/LlamaCppGenerate/Embedding.php index 3a9e0545..90d66e46 100644 --- a/src/Command/LlamaCppGenerate/Embedding.php +++ b/src/Command/LlamaCppGenerate/Embedding.php @@ -7,10 +7,10 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\Command\LlamaCppGenerate; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\JsonSerializer; use Distantmagic\Resonance\LlamaCppClientInterface; use Distantmagic\Resonance\LlamaCppEmbeddingRequest; -use Distantmagic\Resonance\SwooleConfiguration; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -21,11 +21,11 @@ final class Embedding extends LlamaCppGenerate { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly JsonSerializer $jsonSerializer, LlamaCppClientInterface $llamaCppClient, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($llamaCppClient, $swooleConfiguration); + parent::__construct($coroutineDriver, $llamaCppClient); } protected function executeLlamaCppCommand(InputInterface $input, OutputInterface $output, string $prompt): int diff --git a/src/Command/LlamaCppHealth.php b/src/Command/LlamaCppHealth.php index 388391c7..dc558912 100644 --- a/src/Command/LlamaCppHealth.php +++ b/src/Command/LlamaCppHealth.php @@ -7,8 +7,8 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\LlamaCppClientInterface; -use Distantmagic\Resonance\SwooleConfiguration; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -19,10 +19,10 @@ final class LlamaCppHealth extends CoroutineCommand { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly LlamaCppClientInterface $llamaCppClient, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function executeInCoroutine(InputInterface $input, OutputInterface $output): int diff --git a/src/Command/LlamaCppInfill.php b/src/Command/LlamaCppInfill.php index ecb5222f..8df0a8c4 100644 --- a/src/Command/LlamaCppInfill.php +++ b/src/Command/LlamaCppInfill.php @@ -7,10 +7,10 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\JsonSerializer; use Distantmagic\Resonance\LlamaCppClientInterface; use Distantmagic\Resonance\LlamaCppInfillRequest; -use Distantmagic\Resonance\SwooleConfiguration; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -21,11 +21,11 @@ final class LlamaCppInfill extends CoroutineCommand { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly JsonSerializer $jsonSerializer, private readonly LlamaCppClientInterface $llamaCppClient, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function executeInCoroutine(InputInterface $input, OutputInterface $output): int diff --git a/src/Command/MailSend.php b/src/Command/MailSend.php index 8aab03a7..df93a5a9 100644 --- a/src/Command/MailSend.php +++ b/src/Command/MailSend.php @@ -7,10 +7,10 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Attribute\WantsFeature; use Distantmagic\Resonance\Command; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\Feature; use Distantmagic\Resonance\MailerRepository; use RuntimeException; -use Swoole\Event; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -25,6 +25,7 @@ final class MailSend extends Command { public function __construct( + private readonly CoroutineDriverInterface $coroutineDriver, private readonly MailerRepository $mailerRepository, ) { parent::__construct(); @@ -90,8 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ; $this->mailerRepository->mailer->get($transport)->enqueue($email); - - Event::wait(); + $this->coroutineDriver->wait(); return Command::SUCCESS; } diff --git a/src/Command/PostfixBounce.php b/src/Command/PostfixBounce.php index 19c79966..cc3ecd36 100644 --- a/src/Command/PostfixBounce.php +++ b/src/Command/PostfixBounce.php @@ -9,11 +9,11 @@ use Distantmagic\Resonance\Attribute\WantsFeature; use Distantmagic\Resonance\Command; use Distantmagic\Resonance\CoroutineCommand; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\Event\MailBounced; use Distantmagic\Resonance\EventDispatcherInterface; use Distantmagic\Resonance\Feature; use Distantmagic\Resonance\PostfixBounceAnalyzer; -use Distantmagic\Resonance\SwooleConfiguration; use Psr\Log\LoggerInterface; use RuntimeException; use Symfony\Component\Console\Input\InputInterface; @@ -29,12 +29,12 @@ final class PostfixBounce extends CoroutineCommand { public function __construct( + CoroutineDriverInterface $coroutineDriver, private readonly EventDispatcherInterface $eventDispatcher, private readonly LoggerInterface $logger, private readonly PostfixBounceAnalyzer $postfixBounceAnalyzer, - SwooleConfiguration $swooleConfiguration, ) { - parent::__construct($swooleConfiguration); + parent::__construct($coroutineDriver); } protected function executeInCoroutine(InputInterface $input, OutputInterface $output): int diff --git a/src/Command/ServeAmp.php b/src/Command/ServeAmp.php new file mode 100644 index 00000000..081e44b5 --- /dev/null +++ b/src/Command/ServeAmp.php @@ -0,0 +1,28 @@ +ampServer->start(); + } +} diff --git a/src/Command/Serve.php b/src/Command/ServeSwoole.php similarity index 92% rename from src/Command/Serve.php rename to src/Command/ServeSwoole.php index 4efd81d7..803cc48c 100644 --- a/src/Command/Serve.php +++ b/src/Command/ServeSwoole.php @@ -13,11 +13,11 @@ use Symfony\Component\Console\Output\OutputInterface; #[ConsoleCommand( - name: 'serve', + name: 'serve:swoole', description: 'Start combined HTTP and WebSocket server' )] #[WantsFeature(Feature::SwooleTaskServer)] -final class Serve extends Command +final class ServeSwoole extends Command { public function __construct(private readonly SwooleServer $swooleServer) { diff --git a/src/Command/StaticPagesBuild.php b/src/Command/StaticPagesBuild.php index 747e20e9..6d8948eb 100644 --- a/src/Command/StaticPagesBuild.php +++ b/src/Command/StaticPagesBuild.php @@ -7,13 +7,12 @@ use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Attribute\WantsFeature; use Distantmagic\Resonance\Command; +use Distantmagic\Resonance\CoroutineDriverInterface; use Distantmagic\Resonance\Feature; use Distantmagic\Resonance\StaticPageProcessor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use function Distantmagic\Resonance\helpers\coroutineMustRun; - #[ConsoleCommand( name: 'static-pages:build', description: 'Generate static pages' @@ -22,6 +21,7 @@ final class StaticPagesBuild extends Command { public function __construct( + private readonly CoroutineDriverInterface $coroutineDriver, private readonly StaticPageProcessor $staticPageProcessor, ) { parent::__construct(); @@ -29,7 +29,7 @@ public function __construct( protected function execute(InputInterface $input, OutputInterface $output): int { - coroutineMustRun(function () { + $this->coroutineDriver->run(function () { $this->staticPageProcessor->process(); }); diff --git a/src/CoroutineCommand.php b/src/CoroutineCommand.php index ddb4fb0e..456a28f1 100644 --- a/src/CoroutineCommand.php +++ b/src/CoroutineCommand.php @@ -8,8 +8,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use function Distantmagic\Resonance\helpers\coroutineMustRun; - abstract class CoroutineCommand extends SymfonyCommand { abstract protected function executeInCoroutine(InputInterface $input, OutputInterface $output): int; @@ -19,19 +17,14 @@ abstract protected function executeInCoroutine(InputInterface $input, OutputInte * the DI. */ public function __construct( - private readonly SwooleConfiguration $swooleConfiguration, + private readonly CoroutineDriverInterface $coroutineDriver, ) { parent::__construct(); } protected function execute(InputInterface $input, OutputInterface $output): int { - swoole_async_set([ - 'enable_coroutine' => true, - 'log_level' => $this->swooleConfiguration->logLevel, - ]); - - return coroutineMustRun(function () use ($input, $output): int { + return $this->coroutineDriver->run(function () use ($input, $output): int { return $this->executeInCoroutine($input, $output); }); } diff --git a/src/CoroutineDriver.php b/src/CoroutineDriver.php new file mode 100644 index 00000000..646e024d --- /dev/null +++ b/src/CoroutineDriver.php @@ -0,0 +1,7 @@ + $callbacks + * + * @throws CoroutineDriverException + * + * @return array mapped values + */ + public function batch(array $callbacks): array; + + /** + * @psalm-suppress PossiblyUnusedReturnValue used in apps + * + * @param callable() $callback + * + * @throws CoroutineDriverException + */ + public function go(callable $callback): CoroutineReferenceInterface; + + /** + * @throws CoroutineDriverException + */ + public function init(): void; + + /** + * Start the event loop + * + * @template TReturn + * + * @param callable():TReturn $callback + * + * @throws CoroutineDriverException + * + * @return TReturn + */ + public function run(callable $callback): mixed; + + /** + * Wait for all coroutines to finish. + */ + public function wait(): void; +} diff --git a/src/CoroutineReference.php b/src/CoroutineReference.php new file mode 100644 index 00000000..6719b7a9 --- /dev/null +++ b/src/CoroutineReference.php @@ -0,0 +1,7 @@ +coroutineDriver->go(function () use ($cronRegisteredJob): void { $this->logger->info(sprintf('cron_job_start(%s)', $cronRegisteredJob->name)); $cronRegisteredJob->cronJob->onCronTick(); }); diff --git a/src/DatabaseConnectionPoolConfiguration.php b/src/DatabaseConnectionPoolConfiguration.php index 48b7b7f1..5dbf0148 100644 --- a/src/DatabaseConnectionPoolConfiguration.php +++ b/src/DatabaseConnectionPoolConfiguration.php @@ -28,8 +28,6 @@ public function __construct( #[SensitiveParameter] public ?string $password, #[SensitiveParameter] - public bool $poolPrefill, - #[SensitiveParameter] public int $poolSize, #[SensitiveParameter] public int $port, diff --git a/src/DependencyInjectionContainer.php b/src/DependencyInjectionContainer.php index 2bc80ef7..f9e2858c 100644 --- a/src/DependencyInjectionContainer.php +++ b/src/DependencyInjectionContainer.php @@ -16,9 +16,6 @@ use ReflectionClass; use ReflectionFunction; use ReflectionFunctionAbstract; -use Swoole\Event; - -use function Distantmagic\Resonance\helpers\coroutineMustRun; readonly class DependencyInjectionContainer { @@ -51,8 +48,9 @@ */ private Set $wantedFeatures; - public function __construct() - { + public function __construct( + public CoroutineDriverInterface $coroutineDriver, + ) { $this->collections = new Map(); $this->dependencyProviders = new Map(); $this->executedSideEffects = new Set(); @@ -62,6 +60,7 @@ public function __construct() $this->singletons = new SingletonContainer(); $this->singletons->set(static::class, $this); + $this->singletons->set(CoroutineDriverInterface::class, $coroutineDriver); } /** @@ -78,7 +77,7 @@ public function call(Closure $function): mixed /** * @var null|array */ - $parameters = coroutineMustRun(function () use ($function): array { + $parameters = $this->coroutineDriver->run(function () use ($function): array { $reflectionFunction = new ReflectionFunction($function); return $this->makeParameters($reflectionFunction, new DependencyStack()); @@ -90,7 +89,7 @@ public function call(Closure $function): mixed $ret = $function(...$parameters); - Event::wait(); + $this->coroutineDriver->wait(); return $ret; } @@ -124,7 +123,7 @@ public function enableFeature(FeatureInterface $feature): void */ public function make(string $className): object { - $ret = coroutineMustRun(function () use ($className): object { + $ret = $this->coroutineDriver->run(function () use ($className): object { $stack = new DependencyStack(); if ($this->dependencyProviders->hasKey($className)) { diff --git a/src/DialogueNodeTest.php b/src/DialogueNodeTest.php index c873947b..381adb04 100644 --- a/src/DialogueNodeTest.php +++ b/src/DialogueNodeTest.php @@ -13,8 +13,6 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use function Distantmagic\Resonance\helpers\coroutineMustRun; - /** * @internal */ @@ -55,14 +53,14 @@ public function test_dialogue_handles_fuzzy_responses(): void followUp: $marketingNode, )); - coroutineMustRun(static function () use ($marketingNode, $rootNode) { + self::$container->coroutineDriver->run(static function () use ($marketingNode, $rootNode) { $response = $rootNode->respondTo(new UserInput('yep')); self::assertFalse($response->getStatus()->isFailed()); self::assertSame($marketingNode, $response->getFollowUp()); }); - coroutineMustRun(static function () use ($rootNode) { + self::$container->coroutineDriver->run(static function () use ($rootNode) { $response = $rootNode->respondTo(new UserInput('I do not know who I am')); self::assertFalse($response->getStatus()->isFailed()); @@ -129,7 +127,7 @@ public function test_dialogue_produces_response_through_llamacpp(): void followUp: $marketingNode, )); - coroutineMustRun(static function () use ($rootNode) { + self::$container->coroutineDriver->run(static function () use ($rootNode) { $response = $rootNode->respondTo(new UserInput('i am a recruiter')); self::assertFalse($response->getStatus()->isFailed()); diff --git a/src/DoctrineConsoleRunner.php b/src/DoctrineConsoleRunner.php index d50be640..ba8d5442 100644 --- a/src/DoctrineConsoleRunner.php +++ b/src/DoctrineConsoleRunner.php @@ -5,18 +5,16 @@ namespace Distantmagic\Resonance; use Doctrine\ORM\Tools\Console\ConsoleRunner; -use Swoole\Runtime; use Symfony\Component\Console\Application; -use function Distantmagic\Resonance\helpers\coroutineMustRun; - final readonly class DoctrineConsoleRunner { public static function run(DependencyInjectionContainer $container): never { - Runtime::enableCoroutine(SWOOLE_HOOK_ALL); - - $container->call(static function (DoctrineConsoleEntityManagerProvider $entityManagerProvider): never { + $container->call(static function ( + CoroutineDriverInterface $coroutineDriver, + DoctrineConsoleEntityManagerProvider $entityManagerProvider, + ): never { $cli = new Application('Doctrine Command Line Interface'); $cli->setAutoExit(false); @@ -24,7 +22,7 @@ public static function run(DependencyInjectionContainer $container): never ConsoleRunner::addCommands($cli, $entityManagerProvider); - $errorCode = coroutineMustRun(static function () use ($cli): int { + $errorCode = $coroutineDriver->run(static function () use ($cli): int { return $cli->run(); }); diff --git a/src/EsbuildMetaBuilder.php b/src/EsbuildMetaBuilder.php index 91565d5f..5566b07b 100644 --- a/src/EsbuildMetaBuilder.php +++ b/src/EsbuildMetaBuilder.php @@ -9,7 +9,6 @@ use Generator; use LogicException; use RuntimeException; -use Swoole\Coroutine; #[Singleton] readonly class EsbuildMetaBuilder @@ -151,7 +150,7 @@ private function getEsbuildMetaContents(string $esbuildMetafile): string throw new RuntimeException('Esbuild meta manifest is not readable: '.$esbuildMetafile); } - $content = Coroutine::readFile($esbuildMetafile); + $content = file_get_contents($esbuildMetafile); if (!is_string($content)) { throw new RuntimeException('Unable to read esbuild manifest: '.$esbuildMetafile); diff --git a/src/EventDispatcher.php b/src/EventDispatcher.php index 42fe2006..b9cb6849 100644 --- a/src/EventDispatcher.php +++ b/src/EventDispatcher.php @@ -9,13 +9,11 @@ use Distantmagic\SwooleFuture\SwooleFutureResult; use Psr\Log\LoggerInterface; -use function Distantmagic\Resonance\helpers\coroutineMustGo; -use function Swoole\Coroutine\batch; - #[Singleton(provides: EventDispatcherInterface::class)] readonly class EventDispatcher implements EventDispatcherInterface { public function __construct( + private CoroutineDriverInterface $coroutineDriver, private EventListenerAggregate $eventListenerAggregate, private LoggerInterface $logger, ) {} @@ -31,7 +29,7 @@ public function collect(object $event): SwooleFutureResult public function dispatch(object $event): void { - coroutineMustGo(function () use ($event): void { + $this->coroutineDriver->go(function () use ($event): void { $this->doDispatch($event); }); } @@ -59,6 +57,6 @@ private function doDispatch(object $event): array }); } - return batch($batch, DM_BATCH_PROMISE_TIMEOUT); + return $this->coroutineDriver->batch($batch); } } diff --git a/src/HttpResponder/GraphQL.php b/src/HttpResponder/GraphQL.php index dfeea99d..7cefbdf2 100644 --- a/src/HttpResponder/GraphQL.php +++ b/src/HttpResponder/GraphQL.php @@ -66,12 +66,16 @@ public function respond(ServerRequestInterface $request, ResponseInterface $resp ) ; - return new JsonTemplate($this->graphQLAdapter->query( - $swoolePromiseAdapter, - $query, - null, + return new JsonTemplate( $request, - $variables, - )); + $response, + $this->graphQLAdapter->query( + $swoolePromiseAdapter, + $query, + null, + $request, + $variables, + ), + ); } } diff --git a/src/HttpResponderAggregate.php b/src/HttpResponderAggregate.php index c69153eb..d96db433 100644 --- a/src/HttpResponderAggregate.php +++ b/src/HttpResponderAggregate.php @@ -10,38 +10,28 @@ use Distantmagic\Resonance\HttpResponder\Error\MethodNotAllowed; use Distantmagic\Resonance\HttpResponder\Error\PageNotFound; use Distantmagic\Resonance\HttpResponder\Error\ServerError; -use Distantmagic\Resonance\PsrMessage\SwooleServerRequest; -use Distantmagic\Resonance\PsrMessage\SwooleServerResponse; use DomainException; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use Psr\Log\LoggerInterface; use RuntimeException; -use Swoole\Http\Request; -use Swoole\Http\Response; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Throwable; -use function Distantmagic\Resonance\helpers\coroutineMustGetContext; - #[Singleton] readonly class HttpResponderAggregate implements RequestHandlerInterface { public function __construct( - private ApplicationConfiguration $applicationConfiguration, private EventDispatcherInterface $eventDispatcher, private HttpRecursiveResponder $recursiveResponder, private HttpResponderCollection $httpResponderCollection, private HttpRouteMatchRegistry $routeMatchRegistry, - private LoggerInterface $logger, private MethodNotAllowed $methodNotAllowed, private PageNotFound $pageNotFound, - private PsrSwooleResponder $psrSwooleResponder, private RequestContext $requestContext, private ServerError $serverError, private SwooleConfiguration $swooleConfiguration, @@ -66,11 +56,6 @@ public function respondToPsrRequest( $responder = $this->selectResponder($request); try { - $context = coroutineMustGetContext(); - - $context[SwooleContextRequestResponseReader::CONTEXT_KEY_REQUEST] = $request; - $context[SwooleContextRequestResponseReader::CONTEXT_KEY_RESPONSE] = $response; - return $this->recursiveResponder->respondRecursive($request, $response, $responder); } catch (Throwable $throwable) { $this->eventDispatcher->dispatch(new UnhandledException($throwable)); @@ -85,30 +70,6 @@ public function respondToPsrRequest( } } - public function respondToSwooleRequest(Request $request, Response $response): void - { - try { - $psrRequest = new SwooleServerRequest( - applicationConfiguration: $this->applicationConfiguration, - request: $request, - swooleConfiguration: $this->swooleConfiguration, - ); - - $this->psrSwooleResponder->respondWithPsrResponse( - $psrRequest, - $response, - $this->respondToPsrRequest( - $psrRequest, - new SwooleServerResponse($response), - ), - ); - } catch (Throwable $throwable) { - $message = sprintf('http_swoole_responder_failure(%s)', (string) $throwable); - - $this->logger->error($message); - } - } - /** * @param null|non-empty-string $uniqueResponderId */ diff --git a/src/InternalRedirect.php b/src/InternalRedirect.php index e9fff57a..28eca380 100644 --- a/src/InternalRedirect.php +++ b/src/InternalRedirect.php @@ -9,30 +9,23 @@ readonly class InternalRedirect implements HttpInterceptableInterface { - private SwooleContextRequestResponseReader $swooleContextRequestResponseReader; - /** * @param array $params */ public function __construct( + private ServerRequestInterface $request, + private ResponseInterface $response, public HttpRouteSymbolInterface $routeSymbol, public array $params = [], - ?ServerRequestInterface $request = null, - ?ResponseInterface $response = null, - ) { - $this->swooleContextRequestResponseReader = new SwooleContextRequestResponseReader( - request: $request, - response: $response, - ); - } + ) {} public function getResponse(): ResponseInterface { - return $this->swooleContextRequestResponseReader->getResponse(); + return $this->response; } public function getServerRequest(): ServerRequestInterface { - return $this->swooleContextRequestResponseReader->getServerRequest(); + return $this->request; } } diff --git a/src/JsonErrorTemplate.php b/src/JsonErrorTemplate.php index 4d2353c2..d26db184 100644 --- a/src/JsonErrorTemplate.php +++ b/src/JsonErrorTemplate.php @@ -13,7 +13,7 @@ { public function renderHttpError(ServerRequestInterface $request, ResponseInterface $response, HttpError $httpError): HttpInterceptableInterface { - return new JsonTemplate([ + return new JsonTemplate($request, $response, [ 'code' => $httpError->code(), 'message' => $httpError->message($request), ]); diff --git a/src/JsonTemplate.php b/src/JsonTemplate.php index b4a114a0..17b1f446 100644 --- a/src/JsonTemplate.php +++ b/src/JsonTemplate.php @@ -11,26 +11,19 @@ final readonly class JsonTemplate implements HttpInterceptableInterface { - private SwooleContextRequestResponseReader $swooleContextRequestResponseReader; - public function __construct( + private ServerRequestInterface $request, + private ResponseInterface $response, public array|JsonSerializable|string|Stringable $data, - ?ServerRequestInterface $request = null, - ?ResponseInterface $response = null, - ) { - $this->swooleContextRequestResponseReader = new SwooleContextRequestResponseReader( - request: $request, - response: $response, - ); - } + ) {} public function getResponse(): ResponseInterface { - return $this->swooleContextRequestResponseReader->getResponse(); + return $this->response; } public function getServerRequest(): ServerRequestInterface { - return $this->swooleContextRequestResponseReader->getServerRequest(); + return $this->request; } } diff --git a/src/LlamaCppClient.php b/src/LlamaCppClient.php index 289fcc97..3d8521b0 100644 --- a/src/LlamaCppClient.php +++ b/src/LlamaCppClient.php @@ -10,16 +10,14 @@ use Generator; use Psr\Log\LoggerInterface; use RuntimeException; -use Swoole\Coroutine; use Swoole\Coroutine\Channel; -use function Distantmagic\Resonance\helpers\coroutineMustGo; - #[RequiresPhpExtension('curl')] #[Singleton(provides: LlamaCppClientInterface::class)] readonly class LlamaCppClient implements LlamaCppClientInterface { public function __construct( + private CoroutineDriverInterface $coroutineDriver, private JsonSerializer $jsonSerializer, private LlmChatHistoryRenderer $llmChatHistoryRenderer, private LlamaCppConfiguration $llamaCppConfiguration, @@ -181,45 +179,43 @@ private function streamResponse( ): SwooleChannelIterator { $channel = new Channel(1); - coroutineMustGo(function () use ($channel, $path, $requestData, $timeout): void { + $this->coroutineDriver->go(function () use ($channel, $path, $requestData, $timeout): void { $curlHandle = $this->createCurlHandle(); - Coroutine::defer(static function () use ($channel) { + try { + curl_setopt($curlHandle, CURLOPT_TIMEOUT, $timeout); + curl_setopt($curlHandle, CURLOPT_POST, true); + curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $requestData); + curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false); + curl_setopt($curlHandle, CURLOPT_URL, $this->llamaCppLinkBuilder->build($path)); + curl_setopt($curlHandle, CURLOPT_WRITEFUNCTION, function (CurlHandle $curlHandle, string $data) use ($channel): int { + if ($channel->push(new LlamaCppClientResponseChunk( + status: ObservableTaskStatus::Running, + chunk: $data + ), $this->llamaCppConfiguration->completionTokenTimeout)) { + return strlen($data); + } + + return 0; + }); + + if (false === curl_exec($curlHandle)) { + $curlErrno = curl_errno($curlHandle); + + if (CURLE_WRITE_ERROR !== $curlErrno) { + $this->logger->error(new CurlErrorMessage($curlHandle)); + + $channel->push(new LlamaCppClientResponseChunk( + status: ObservableTaskStatus::Failed, + chunk: '', + ), $this->llamaCppConfiguration->completionTokenTimeout); + } + } else { + $this->assertStatusCode($curlHandle, 200); + } + } finally { $channel->close(); - }); - - Coroutine::defer(static function () use ($curlHandle) { curl_close($curlHandle); - }); - - curl_setopt($curlHandle, CURLOPT_TIMEOUT, $timeout); - curl_setopt($curlHandle, CURLOPT_POST, true); - curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $requestData); - curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false); - curl_setopt($curlHandle, CURLOPT_URL, $this->llamaCppLinkBuilder->build($path)); - curl_setopt($curlHandle, CURLOPT_WRITEFUNCTION, function (CurlHandle $curlHandle, string $data) use ($channel): int { - if ($channel->push(new LlamaCppClientResponseChunk( - status: ObservableTaskStatus::Running, - chunk: $data - ), $this->llamaCppConfiguration->completionTokenTimeout)) { - return strlen($data); - } - - return 0; - }); - if (false === curl_exec($curlHandle)) { - $curlErrno = curl_errno($curlHandle); - - if (CURLE_WRITE_ERROR !== $curlErrno) { - $this->logger->error(new CurlErrorMessage($curlHandle)); - - $channel->push(new LlamaCppClientResponseChunk( - status: ObservableTaskStatus::Failed, - chunk: '', - ), $this->llamaCppConfiguration->completionTokenTimeout); - } - } else { - $this->assertStatusCode($curlHandle, 200); } }); diff --git a/src/LlamaCppClientTest.php b/src/LlamaCppClientTest.php index c1abf98c..31316de8 100644 --- a/src/LlamaCppClientTest.php +++ b/src/LlamaCppClientTest.php @@ -7,9 +7,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use Swoole\Event; - -use function Distantmagic\Resonance\helpers\coroutineMustRun; /** * @internal @@ -22,14 +19,14 @@ final class LlamaCppClientTest extends TestCase protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } public function test_completion_is_generated(): void { $llamaCppClient = self::$container->make(LlamaCppClient::class); - coroutineMustRun(static function () use ($llamaCppClient) { + self::$container->coroutineDriver->run(static function () use ($llamaCppClient) { $completion = $llamaCppClient->generateCompletion(new LlamaCppCompletionRequest( llmChatHistory: new LlmChatHistory([ new LlmChatMessage('user', 'Who are you? Answer in exactly two words.'), diff --git a/src/LlamaCppExtractSubjectTest.php b/src/LlamaCppExtractSubjectTest.php index 8470e5a8..66c82e61 100644 --- a/src/LlamaCppExtractSubjectTest.php +++ b/src/LlamaCppExtractSubjectTest.php @@ -9,9 +9,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use Swoole\Event; - -use function Distantmagic\Resonance\helpers\coroutineMustRun; /** * @internal @@ -69,7 +66,7 @@ public static function inputSubjectProvider(): Generator protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } #[DataProvider('inputSubjectProvider')] @@ -77,7 +74,7 @@ public function test_application_name_is_provided(string $topic, string $input, { $llamaCppExtract = self::$container->make(LlamaCppExtractSubject::class); - coroutineMustRun(static function () use ($expected, $input, $llamaCppExtract, $topic) { + self::$container->coroutineDriver->run(static function () use ($expected, $input, $llamaCppExtract, $topic) { $extracted = $llamaCppExtract->extract( topic: $topic, input: $input, diff --git a/src/LlamaCppExtractWhenTest.php b/src/LlamaCppExtractWhenTest.php index c17cee19..2509392c 100644 --- a/src/LlamaCppExtractWhenTest.php +++ b/src/LlamaCppExtractWhenTest.php @@ -9,9 +9,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use Swoole\Event; - -use function Distantmagic\Resonance\helpers\coroutineMustRun; /** * @internal @@ -93,7 +90,7 @@ public static function inputSubjectProvider(): Generator protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } #[DataProvider('inputSubjectProvider')] @@ -104,7 +101,7 @@ public function test_llm_checks_if_user_mentiones_a_thing( ): void { $llamaCppExtract = self::$container->make(LlamaCppExtractWhen::class); - coroutineMustRun(static function () use ($expected, $input, $condition, $llamaCppExtract) { + self::$container->coroutineDriver->run(static function () use ($expected, $input, $condition, $llamaCppExtract) { $extracted = $llamaCppExtract->extract( input: $input, condition: $condition, diff --git a/src/LlamaCppExtractYesNoMaybeTest.php b/src/LlamaCppExtractYesNoMaybeTest.php index 96f6b2f3..fe495bbc 100644 --- a/src/LlamaCppExtractYesNoMaybeTest.php +++ b/src/LlamaCppExtractYesNoMaybeTest.php @@ -9,9 +9,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use Swoole\Event; - -use function Distantmagic\Resonance\helpers\coroutineMustRun; /** * @internal @@ -57,7 +54,7 @@ public static function inputSubjectProvider(): Generator protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } #[DataProvider('inputSubjectProvider')] @@ -65,7 +62,7 @@ public function test_application_name_is_provided(string $input, YesNoMaybe $exp { $llamaCppExtract = self::$container->make(LlamaCppExtractYesNoMaybe::class); - coroutineMustRun(static function () use ($expected, $input, $llamaCppExtract) { + self::$container->coroutineDriver->run(static function () use ($expected, $input, $llamaCppExtract) { $extracted = $llamaCppExtract->extract(input: $input); self::assertSame($expected, $extracted->result); diff --git a/src/OAuth2AuthorizationCodeFlowController.php b/src/OAuth2AuthorizationCodeFlowController.php index ead1fe62..261a4fab 100644 --- a/src/OAuth2AuthorizationCodeFlowController.php +++ b/src/OAuth2AuthorizationCodeFlowController.php @@ -95,7 +95,7 @@ public function redirectToAuthenticatedPage( ->getHttpRouteSymbolForEndpoint(OAuth2Endpoint::AuthenticatedPage) ; - return new InternalRedirect($routeSymbol); + return new InternalRedirect($request, $response, $routeSymbol); } public function redirectToClientScopeConsentPage( @@ -107,7 +107,7 @@ public function redirectToClientScopeConsentPage( ->getHttpRouteSymbolForEndpoint(OAuth2Endpoint::ClientScopeConsentForm) ; - return new InternalRedirect($routeSymbol); + return new InternalRedirect($request, $response, $routeSymbol); } public function redirectToLoginPage( @@ -119,6 +119,6 @@ public function redirectToLoginPage( ->getHttpRouteSymbolForEndpoint(OAuth2Endpoint::LoginForm) ; - return new InternalRedirect($routeSymbol); + return new InternalRedirect($request, $response, $routeSymbol); } } diff --git a/src/OAuth2UserSessionAuthenticated.php b/src/OAuth2UserSessionAuthenticated.php index 998d33b8..1cfcd2ce 100644 --- a/src/OAuth2UserSessionAuthenticated.php +++ b/src/OAuth2UserSessionAuthenticated.php @@ -9,28 +9,21 @@ final readonly class OAuth2UserSessionAuthenticated implements HttpInterceptableInterface { - private SwooleContextRequestResponseReader $swooleContextRequestResponseReader; - /** * @psalm-taint-source file $templatePath */ public function __construct( - ?ServerRequestInterface $request = null, - ?ResponseInterface $response = null, - ) { - $this->swooleContextRequestResponseReader = new SwooleContextRequestResponseReader( - request: $request, - response: $response, - ); - } + private ServerRequestInterface $request, + private ResponseInterface $response, + ) {} public function getResponse(): ResponseInterface { - return $this->swooleContextRequestResponseReader->getResponse(); + return $this->response; } public function getServerRequest(): ServerRequestInterface { - return $this->swooleContextRequestResponseReader->getServerRequest(); + return $this->request; } } diff --git a/src/ObservableTaskTable.php b/src/ObservableTaskTable.php index 8b18725d..3653a640 100644 --- a/src/ObservableTaskTable.php +++ b/src/ObservableTaskTable.php @@ -9,11 +9,8 @@ use Generator; use IteratorAggregate; use RuntimeException; -use Swoole\Coroutine; use Swoole\Table; -use function Distantmagic\Resonance\helpers\coroutineMustGo; - /** * @template-implements IteratorAggregate */ @@ -25,6 +22,7 @@ private Table $table; public function __construct( + private CoroutineDriverInterface $coroutineDriver, ObservableTaskConfiguration $observableTaskConfiguration, private SerializerInterface $serializer, ) { @@ -80,37 +78,37 @@ public function observe(ObservableTaskInterface $observableTask): string { $slotId = $this->availableRowsPool->nextAvailableRow(); - coroutineMustGo(function () use ($slotId, $observableTask) { - Coroutine::defer(function () use ($slotId) { - $this->availableRowsPool->freeAvailableRow($slotId); - }); - - if ( - !$this->table->set($slotId, [ - 'category' => $observableTask->getCategory(), - 'modified_at' => time(), - 'name' => $observableTask->getName(), - 'status' => $this->serializedPendingStatus, - ]) - ) { - throw new RuntimeException('Unable to set an initial slot status'); - } - - foreach ($observableTask as $statusUpdate) { + $this->coroutineDriver->go(function () use ($slotId, $observableTask) { + try { if ( !$this->table->set($slotId, [ 'category' => $observableTask->getCategory(), 'modified_at' => time(), 'name' => $observableTask->getName(), - 'status' => $this->serializer->serialize($statusUpdate), + 'status' => $this->serializedPendingStatus, ]) ) { - throw new RuntimeException('Unable to update a slot status.'); + throw new RuntimeException('Unable to set an initial slot status'); } - if ($statusUpdate->status->isFinal()) { - break; + foreach ($observableTask as $statusUpdate) { + if ( + !$this->table->set($slotId, [ + 'category' => $observableTask->getCategory(), + 'modified_at' => time(), + 'name' => $observableTask->getName(), + 'status' => $this->serializer->serialize($statusUpdate), + ]) + ) { + throw new RuntimeException('Unable to update a slot status.'); + } + + if ($statusUpdate->status->isFinal()) { + break; + } } + } finally { + $this->availableRowsPool->freeAvailableRow($slotId); } }); diff --git a/src/ObservableTaskTableTest.php b/src/ObservableTaskTableTest.php index 06e9cf96..77f5ee30 100644 --- a/src/ObservableTaskTableTest.php +++ b/src/ObservableTaskTableTest.php @@ -7,7 +7,6 @@ use Distantmagic\Resonance\Serializer\Vanilla; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Swoole\Event; /** * @internal @@ -15,6 +14,8 @@ #[CoversClass(ObservableTaskTable::class)] final class ObservableTaskTableTest extends TestCase { + use TestsDependencyInectionContainerTrait; + private ?ObservableTaskConfiguration $observableTaskConfiguration = null; private ?ObservableTaskTable $observableTaskTable = null; @@ -26,6 +27,7 @@ protected function setUp(): void ); $this->observableTaskTable = new ObservableTaskTable( + coroutineDriver: self::$container->coroutineDriver, observableTaskConfiguration: $this->observableTaskConfiguration, serializer: new Vanilla(), ); @@ -33,7 +35,7 @@ protected function setUp(): void protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } public function test_task_is_observed(): void diff --git a/src/PostfixBounceAnalyzer.php b/src/PostfixBounceAnalyzer.php index c5d649fe..691ff221 100644 --- a/src/PostfixBounceAnalyzer.php +++ b/src/PostfixBounceAnalyzer.php @@ -65,10 +65,10 @@ public function extractReport(string $deliveryReport): ?PostfixBounceReport if (isset($ret['original-recipient']) && !empty($ret['original-recipient'])) { return new PostfixBounceReport( recipient: new Address($ret['original-recipient']), - diagnosticCode: empty($ret['diagnostic-code']) ? null : $ret['diagnostic-code'], - notification: empty($ret['notification']) ? null : $ret['notification'], - sender: empty($ret['x-postfix-sender']) ? null : new Address($ret['x-postfix-sender']), - status: empty($ret['status']) ? null : $ret['status'], + diagnosticCode: '' === $ret['diagnostic-code'] ? null : $ret['diagnostic-code'], + notification: '' === $ret['notification'] ? null : $ret['notification'], + sender: '' === $ret['x-postfix-sender'] ? null : new Address($ret['x-postfix-sender']), + status: '' === $ret['status'] ? null : $ret['status'], ); } diff --git a/src/PromptSubjectResponderAggregate.php b/src/PromptSubjectResponderAggregate.php index 77beb6b5..f62bd803 100644 --- a/src/PromptSubjectResponderAggregate.php +++ b/src/PromptSubjectResponderAggregate.php @@ -8,12 +8,11 @@ use Generator; use Psr\Log\LoggerInterface; -use function Distantmagic\Resonance\helpers\coroutineMustGo; - #[Singleton] readonly class PromptSubjectResponderAggregate { public function __construct( + private CoroutineDriverInterface $coroutineDriver, private LoggerInterface $logger, private PromptSubjectResponderCollection $promptSubjectResponderCollection, ) {} @@ -111,7 +110,7 @@ private function respondWithSubjectAction( ); $response = new PromptSubjectResponse($inactivityTimeout); - coroutineMustGo(static function () use ($request, $responder, $response) { + $this->coroutineDriver->go(static function () use ($request, $responder, $response) { $responder->respondToPromptSubject($request, $response); }); diff --git a/src/PsrAmpResponder.php b/src/PsrAmpResponder.php new file mode 100644 index 00000000..4be74645 --- /dev/null +++ b/src/PsrAmpResponder.php @@ -0,0 +1,105 @@ +> $headers + */ + $headers = $response->getHeaders(); + + $ampResponse = new Response( + headers: $headers, + body: $response->getBody()->getContents(), + ); + + $ampResponse->setStatus( + $response->getStatusCode(), + $response->getReasonPhrase(), + ); + + // /** + // * @var null|string $sendfile + // */ + // $sendfile = null; + + // foreach ($response->getHeaders() as $name => $values) { + // $headerLine = implode(', ', $values); + + // if ('x-sendfile' !== $name) { + // $response->header((string) $name, $headerLine); + // } else { + // $sendfile = $headerLine; + // } + // } + + foreach ($this->cookieManager->getCookieJar($request) as $cookie) { + $cookieName = $cookie->getName(); + + if (!empty($cookieName)) { + $ampResponse->setCookie(new ResponseCookie( + name: $cookieName, + value: $cookie->getValue() ?? '', + attributes: $this->createCookieAttributes($cookie), + )); + } + } + + // if (is_string($sendfile)) { + // if (!$response->sendfile($sendfile)) { + // $response->status(500, 'Unable to send file'); + // } + + // return; + // } + + return $ampResponse; + } + + private function createCookieAttributes(Cookie $cookie): CookieAttributes + { + $cookieAttributes = CookieAttributes::default(); + $expiresAt = (new DateTimeImmutable())->setTimestamp($cookie->getExpiresTime()); + + $cookieAttributes = $cookieAttributes + ->withDomain($cookie->getDomain() ?? '') + ->withExpiry($expiresAt) + ->withPath($cookie->getPath()) + ; + + $cookieAttributes = $cookie->isSecure() + ? $cookieAttributes->withSecure() + : $cookieAttributes->withoutSecure(); + + $cookieAttributes = $cookie->isHttpOnly() + ? $cookieAttributes->withHttpOnly() + : $cookieAttributes->withoutHttpOnly(); + + $sameSite = $cookie->getSameSite(); + + return $sameSite + ? $cookieAttributes->withSameSite($sameSite) + : $cookieAttributes->withoutSameSite(); + } +} diff --git a/src/PsrMessage/AmpServerRequest.php b/src/PsrMessage/AmpServerRequest.php new file mode 100644 index 00000000..2bd54de4 --- /dev/null +++ b/src/PsrMessage/AmpServerRequest.php @@ -0,0 +1,223 @@ +getCookies(); + $psrCookieParams = []; + $requestContents = $request->getBody()->buffer(); + + foreach ($cookies as $cookie) { + $psrCookieParams[$cookie->getName()] = $cookie->getValue(); + } + + $this->body = new PsrStringStream($requestContents); + $this->psrCookieParams = $psrCookieParams; + $this->serverParams = $_SERVER; + } + + public function getAttribute(string $name, $default = null): mixed + { + return $default; + } + + public function getAttributes(): array + { + return []; + } + + public function getBody(): StreamInterface + { + return $this->body; + } + + public function getCookieParams(): array + { + return $this->psrCookieParams; + } + + public function getHeader($name): array + { + return $this->request->getHeaderArray($name); + } + + public function getHeaderLine(string $name): string + { + return implode(', ', $this->getHeader($name)); + } + + public function getHeaders(): array + { + return $this->request->getHeaders(); + } + + public function getMethod(): string + { + return $this->request->getMethod(); + } + + public function getParsedBody(): ?array + { + return Form::fromRequest($this->request)->getValues(); + } + + public function getProtocolVersion(): string + { + if (!array_key_exists('SERVER_PROTOCOL', $this->serverParams)) { + return ''; + } + + /** + * @var mixed explicitly mixed for typechecks + */ + $serverProtocol = $this->serverParams['SERVER_PROTOCOL']; + + if (is_string($serverProtocol)) { + return $serverProtocol; + } + + return ''; + } + + public function getQueryParams(): array + { + return $this->request->getQueryParameters(); + } + + public function getRequestTarget(): string + { + $uri = $this->getUri(); + $path = $uri->getPath(); + + $target = ''; + + if ('' === $path) { + $target = '/'; + } + + $query = $uri->getQuery(); + + if ('' !== $query) { + $target .= '?'.$query; + } + + return $target; + } + + public function getServerParams(): array + { + return $this->serverParams; + } + + /** + * @return array + */ + public function getUploadedFiles(): array + { + return []; + } + + public function getUri(): UriInterface + { + return $this->request->getUri(); + } + + public function hasHeader(string $name): bool + { + return $this->request->hasHeader($name); + } + + public function withAddedHeader($name, $value): never + { + $this->throwReadOnly(); + } + + public function withAttribute(string $name, mixed $value): never + { + $this->throwReadOnly(); + } + + public function withBody(StreamInterface $body): never + { + $this->throwReadOnly(); + } + + public function withCookieParams(array $cookies): never + { + $this->throwReadOnly(); + } + + public function withHeader($name, $value): never + { + $this->throwReadOnly(); + } + + public function withMethod($method): never + { + $this->throwReadOnly(); + } + + public function withoutAttribute(string $name): never + { + $this->throwReadOnly(); + } + + public function withoutHeader($name): never + { + $this->throwReadOnly(); + } + + public function withParsedBody($data): never + { + $this->throwReadOnly(); + } + + public function withProtocolVersion($version): never + { + $this->throwReadOnly(); + } + + public function withQueryParams(array $query): never + { + $this->throwReadOnly(); + } + + public function withRequestTarget($requestTarget): never + { + $this->throwReadOnly(); + } + + public function withUploadedFiles(array $uploadedFiles): never + { + $this->throwReadOnly(); + } + + public function withUri(UriInterface $uri, $preserveHost = false): never + { + $this->throwReadOnly(); + } + + private function throwReadOnly(): never + { + throw new LogicException('This request is readonly'); + } +} diff --git a/src/PsrMessage/SwooleServerResponse.php b/src/PsrMessage/ServerResponse.php similarity index 94% rename from src/PsrMessage/SwooleServerResponse.php rename to src/PsrMessage/ServerResponse.php index 80651ba9..f4a95a98 100644 --- a/src/PsrMessage/SwooleServerResponse.php +++ b/src/PsrMessage/ServerResponse.php @@ -10,15 +10,13 @@ use LogicException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; -use Swoole\Http\Response; -readonly class SwooleServerResponse extends PsrMessage implements ResponseInterface +readonly class ServerResponse extends PsrMessage implements ResponseInterface { /** * @param Map> $headers */ public function __construct( - private Response $response, private StreamInterface $body = new PsrStringStream(''), private int $code = 200, private Map $headers = new Map(), @@ -84,7 +82,6 @@ public function withBody(StreamInterface $body): self * @var static */ return new self( - $this->response, $body, $this->code, $this->headers, @@ -123,7 +120,6 @@ public function withProtocolVersion(string $version): static * @var static */ return new self( - $this->response, $this->body, $this->code, $this->headers, @@ -143,7 +139,6 @@ public function withStatus(int $code, string $reasonPhrase = ''): static * @var static */ return new self( - $this->response, $this->body, $code, $this->headers, @@ -162,7 +157,6 @@ private function copyWithHeaders(Map $headersCopy): static * @var static */ return new self( - $this->response, $this->body, $this->code, $headersCopy, diff --git a/src/RedisConnectionPoolConfiguration.php b/src/RedisConnectionPoolConfiguration.php index e3cdc8e0..67ff8ebf 100644 --- a/src/RedisConnectionPoolConfiguration.php +++ b/src/RedisConnectionPoolConfiguration.php @@ -12,7 +12,6 @@ * @psalm-taint-source system_secret $dbIndex * @psalm-taint-source system_secret $host * @psalm-taint-source system_secret $password - * @psalm-taint-source system_secret $poolPrefill * @psalm-taint-source system_secret $poolSize * @psalm-taint-source system_secret $port * @psalm-taint-source system_secret $prefix @@ -29,8 +28,6 @@ public function __construct( #[SensitiveParameter] public string $password, #[SensitiveParameter] - public bool $poolPrefill, - #[SensitiveParameter] public int $poolSize, #[SensitiveParameter] public int $port, diff --git a/src/SingletonProvider/ConfigurationProvider/DatabaseConfigurationProvider.php b/src/SingletonProvider/ConfigurationProvider/DatabaseConfigurationProvider.php index 3f096b8a..1c431b62 100644 --- a/src/SingletonProvider/ConfigurationProvider/DatabaseConfigurationProvider.php +++ b/src/SingletonProvider/ConfigurationProvider/DatabaseConfigurationProvider.php @@ -76,7 +76,6 @@ protected function provideConfiguration($validatedData): DatabaseConfiguration host: $connectionPoolConfiguration['host'], logQueries: $connectionPoolConfiguration['log_queries'], password: $connectionPoolConfiguration['password'], - poolPrefill: $connectionPoolConfiguration['pool_prefill'], poolSize: $connectionPoolConfiguration['pool_size'], port: $connectionPoolConfiguration['port'], unixSocket: $connectionPoolConfiguration['unix_socket'], diff --git a/src/SingletonProvider/ConfigurationProvider/OAuth2ConfigurationProvider.php b/src/SingletonProvider/ConfigurationProvider/OAuth2ConfigurationProvider.php index a1b0bc31..b2573ee6 100644 --- a/src/SingletonProvider/ConfigurationProvider/OAuth2ConfigurationProvider.php +++ b/src/SingletonProvider/ConfigurationProvider/OAuth2ConfigurationProvider.php @@ -16,7 +16,6 @@ use Distantmagic\Resonance\SingletonProvider\ConfigurationProvider; use League\OAuth2\Server\CryptKey; use RuntimeException; -use Swoole\Coroutine; /** * @template-extends ConfigurationProviderpoolSize, ); - if ($connectionPoolConfiguration->poolPrefill) { - $pdoPool->fill(); - } - $databaseConnectionPoolRepository->databaseConnectionPool->put($name, $pdoPool); } diff --git a/src/SingletonProvider/RedisConnectionPoolRepositoryProvider.php b/src/SingletonProvider/RedisConnectionPoolRepositoryProvider.php index 2f8f4a26..86104fc0 100644 --- a/src/SingletonProvider/RedisConnectionPoolRepositoryProvider.php +++ b/src/SingletonProvider/RedisConnectionPoolRepositoryProvider.php @@ -39,14 +39,14 @@ public function provide(SingletonContainer $singletons, PHPProjectFiles $phpProj ; $redisPool = new RedisPool($redisConfig, $connectionPoolConfiguration->poolSize); - - if ($connectionPoolConfiguration->poolPrefill) { - $redisPool->fill(); - } - $redisConnectionPoolRepository->redisConnectionPool->put($name, $redisPool); } return $redisConnectionPoolRepository; } + + public function shouldRegister(): bool + { + return false; + } } diff --git a/src/SwooleContextRequestResponseReader.php b/src/SwooleContextRequestResponseReader.php deleted file mode 100644 index f25e44aa..00000000 --- a/src/SwooleContextRequestResponseReader.php +++ /dev/null @@ -1,61 +0,0 @@ -request = $request; - $this->response = $response; - - return; - } - - $context = coroutineMustGetContext(); - - /** - * @var mixed explicitly mixed for typechecks - */ - $request ??= $context[self::CONTEXT_KEY_REQUEST]; - - Assertion::isInstanceOf($request, ServerRequestInterface::class); - - /** - * @var mixed explicitly mixed for typechecks - */ - $response ??= $context[self::CONTEXT_KEY_RESPONSE]; - - Assertion::isInstanceOf($response, ResponseInterface::class); - - $this->request = $request; - $this->response = $response; - } - - public function getResponse(): ResponseInterface - { - return $this->response; - } - - public function getServerRequest(): ServerRequestInterface - { - return $this->request; - } -} diff --git a/src/SwooleServer.php b/src/SwooleServer.php index e9d6a543..ba334c9c 100644 --- a/src/SwooleServer.php +++ b/src/SwooleServer.php @@ -8,12 +8,15 @@ use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\Event\HttpServerBeforeStop; use Distantmagic\Resonance\Event\HttpServerStarted; +use Distantmagic\Resonance\PsrMessage\ServerResponse; +use Distantmagic\Resonance\PsrMessage\SwooleServerRequest; use Psr\Log\LoggerInterface; use Swoole\Http\Request; use Swoole\Http\Response; use Swoole\Http\Server as HttpServer; use Swoole\Server; use Swoole\WebSocket\Server as WebSocketServer; +use Throwable; #[GrantsFeature(Feature::SwooleTaskServer)] #[Singleton] @@ -26,6 +29,7 @@ public function __construct( private EventDispatcherInterface $eventDispatcher, private HttpResponderAggregate $httpResponderAggregate, private LoggerInterface $logger, + private PsrSwooleResponder $psrSwooleResponder, private ServerPipeMessageDispatcher $serverPipeMessageDispatcher, private ServerTaskHandlerDispatcher $serverTaskHandlerDispatcher, private SwooleConfiguration $swooleConfiguration, @@ -79,7 +83,7 @@ public function start(): bool $this->server->on('beforeShutdown', $this->onBeforeShutdown(...)); $this->server->on('finish', $this->serverTaskHandlerDispatcher->onFinish(...)); $this->server->on('pipeMessage', $this->serverPipeMessageDispatcher->onPipeMessage(...)); - $this->server->on('request', $this->httpResponderAggregate->respondToSwooleRequest(...)); + $this->server->on('request', $this->onRequest(...)); $this->server->on('start', $this->onStart(...)); $this->server->on('task', $this->serverTaskHandlerDispatcher->onTask(...)); $this->server->on('workerError', $this->onWorkerError(...)); @@ -116,6 +120,30 @@ private function onHandshake(Request $request, Response $response): void $this->webSocketServerController->onHandshake($this->server, $request, $response); } + private function onRequest(Request $request, Response $response): void + { + try { + $psrRequest = new SwooleServerRequest( + applicationConfiguration: $this->applicationConfiguration, + request: $request, + swooleConfiguration: $this->swooleConfiguration, + ); + + $this->psrSwooleResponder->respondWithPsrResponse( + $psrRequest, + $response, + $this->httpResponderAggregate->respondToPsrRequest( + request: $psrRequest, + response: new ServerResponse(), + ), + ); + } catch (Throwable $throwable) { + $message = sprintf('http_swoole_responder_failure(%s)', (string) $throwable); + + $this->logger->error($message); + } + } + private function onStart(Server $server): void { $this->eventDispatcher->dispatch(new HttpServerStarted($server)); diff --git a/src/SwooleTimeoutTest.php b/src/SwooleTimeoutTest.php index 2e2c8078..daaf5b52 100644 --- a/src/SwooleTimeoutTest.php +++ b/src/SwooleTimeoutTest.php @@ -6,7 +6,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Swoole\Event; /** * @internal @@ -15,9 +14,11 @@ #[CoversClass(SwooleTimeoutScheduled::class)] final class SwooleTimeoutTest extends TestCase { + use TestsDependencyInectionContainerTrait; + protected function tearDown(): void { - Event::wait(); + self::$container->coroutineDriver->wait(); } public function test_code_executes_after_timeout(): void diff --git a/src/TwigTemplate.php b/src/TwigTemplate.php index 907f4930..dc69cf7b 100644 --- a/src/TwigTemplate.php +++ b/src/TwigTemplate.php @@ -9,31 +9,24 @@ final readonly class TwigTemplate implements HttpInterceptableInterface { - private SwooleContextRequestResponseReader $swooleContextRequestResponseReader; - /** * @psalm-taint-source file $templatePath */ public function __construct( + private ServerRequestInterface $request, + private ResponseInterface $response, private string $templatePath, private array $templateData = [], - ?ServerRequestInterface $request = null, - ?ResponseInterface $response = null, - ) { - $this->swooleContextRequestResponseReader = new SwooleContextRequestResponseReader( - request: $request, - response: $response, - ); - } + ) {} public function getResponse(): ResponseInterface { - return $this->swooleContextRequestResponseReader->getResponse(); + return $this->response; } public function getServerRequest(): ServerRequestInterface { - return $this->swooleContextRequestResponseReader->getServerRequest(); + return $this->request; } public function getTemplateData(ServerRequestInterface $request, ResponseInterface $response): array diff --git a/src/helpers/coroutineMustGetContext.php b/src/helpers/coroutineMustGetContext.php deleted file mode 100644 index 25d969cf..00000000 --- a/src/helpers/coroutineMustGetContext.php +++ /dev/null @@ -1,23 +0,0 @@ -