From ea533ddd20fdd00a2477e2dbc377fa7a7dc005d3 Mon Sep 17 00:00:00 2001 From: Pato05 Date: Fri, 8 Mar 2024 01:49:03 +0100 Subject: [PATCH] upgrade to amphp/amp ^3.0, migrate to fibers! - removed continueScan from Session, as the command is not supported there - add unit tests --- .gitignore | 2 + .php-cs-fixer.dist.php | 5 +- README.md | 75 +- composer.json | 76 +- composer.lock | 3437 ------------------------------------- examples/scan.php | 27 +- examples/scan_stream.php | 33 +- lib/Base.php | 98 +- lib/ClamAV.php | 74 +- lib/ClamException.php | 12 +- lib/ParseException.php | 2 +- lib/ScanResult.php | 10 +- lib/Session.php | 90 +- lib/functions.php | 61 +- phpunit.xml | 26 + tests/ClamAVErrorTest.php | 38 + tests/ClamAVTest.php | 86 + tests/eicar.com | 1 + tests/harmless.txt | 1 + 19 files changed, 398 insertions(+), 3756 deletions(-) delete mode 100644 composer.lock create mode 100644 phpunit.xml create mode 100644 tests/ClamAVErrorTest.php create mode 100644 tests/ClamAVTest.php create mode 100755 tests/eicar.com create mode 100644 tests/harmless.txt diff --git a/.gitignore b/.gitignore index 69bd16e..db4fdbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /vendor/ .php-cs-fixer.cache +.phpunit.result.cache +composer.lock diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 138406d..2366a55 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -2,8 +2,9 @@ $config = new Amp\CodeStyle\Config; $config->getFinder() - ->in(__DIR__ . "/examples") - ->in(__DIR__ . "/lib"); + ->in(__DIR__ . '/examples') + ->in(__DIR__ . '/lib') + ->in(__DIR__ . '/tests'); $config->setCacheFile(__DIR__ . '/.php-cs-fixer.cache'); diff --git a/README.md b/README.md index 00f37cc..e768429 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,15 @@ # amphp-clamav +![license: MIT](https://img.shields.io/badge/license-MIT-blue) + An asynchronous ClamAV wrapper written with amphp/socket +## Migrating from v1.x.x + +The updated v2.0.0 brought some breaking changes because of the changes in the underlying `amphp/amp`. These underlying changes give a great boost to the asynchronous event loop, being it now based on `Fibers` instead of `Generators`. + +Mostly you only need to remove the `yield` keyword before any calls to the library's asynchronous function. Learn more on [Amp's Upgrade Guide](https://amphp.org/upgrade). + ## Installing ``` @@ -10,66 +18,9 @@ composer require pato05/amphp-clamav ## Examples -Ping and scan of a file/directory - -[`examples/scan.php`](https://github.com/Pato05/amphp-clamav/blob/main/examples/scan.php): - -```php -close(); // always close files to avoid memory leaks - echo (string) $res . PHP_EOL; -}); -``` +Scanning from a `ReadableStream` (in this case a `File` instance which implements `ReadableStream`): [`examples/scan_stream.php`](https://github.com/Pato05/amphp-clamav/blob/main/examples/scan_stream.php) ## Using a TCP/IP socket instead @@ -90,7 +41,7 @@ MULTISCAN is supported but can only be used on non-session instances (due to a C MULTISCAN allows you to make a multithreaded scan. ```php -$result = yield \Amp\ClamAV\multiScan('FILEPATH'); +$result = \Amp\ClamAV\multiScan('FILEPATH'); ``` ## Differences between running a session and without @@ -100,13 +51,13 @@ Sessions run on the same socket connection, while non-session instances will rec Instantiating a session is pretty straight forward, just use the `ClamAV::session()` method like this: ```php -$clamSession = yield \Amp\ClamAV\session(); +$clamSession = \Amp\ClamAV\session(); ``` Though you MUST end every session by using the method `Session::end()`: ```php -yield $clamSession->end(); +$clamSession->end(); ``` Be aware that in a session you can only execute ONE COMMAND AT A TIME, therefore, if you want to run more than one command in parallel, use the main `ClamAV` class instead. diff --git a/composer.json b/composer.json index a0051f6..8cde5e8 100644 --- a/composer.json +++ b/composer.json @@ -1,41 +1,45 @@ { - "name": "pato05/amphp-clamav", - "description": "An asynchronous clamd wrapper written with amphp/socket", - "type": "library", - "require": { - "php": "^8.0", - "amphp/amp": "^2.6", - "amphp/socket": "^1.2", - "ext-sockets": "*" + "name": "pato05/amphp-clamav", + "description": "An asynchronous clamd wrapper written with amphp/socket", + "type": "library", + "require": { + "php": "^8.0", + "amphp/amp": "^3.0", + "amphp/socket": "^2.0", + "ext-sockets": "*" + }, + "license": "MIT", + "autoload": { + "psr-4": { + "Amp\\ClamAV\\": "lib/" }, - "license": "MIT", - "autoload": { - "psr-4": { - "Amp\\ClamAV\\": "lib/" - }, - "files": [ - "lib/functions.php" - ] - }, - "authors": [ - { - "name": "Pato05", - "email": "pato05mc@gmail.com" - } + "files": [ + "lib/functions.php" + ] + }, + "authors": [ + { + "name": "Pato05", + "email": "pato05mc@gmail.com" + } + ], + "require-dev": { + "amphp/php-cs-fixer-config": "^2.0", + "amphp/file": "^3.0", + "amphp/phpunit-util": "^3.0", + "phpunit/phpunit": "^9.6" + }, + "scripts": { + "check": [ + "@fix", + "@test" ], - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/file": "^2.0", - "phabel/phabel": "1.0.49.80" - }, - "config": { - "allow-plugins": { - "phabel/phabel": true - } - }, - "extra": { - "phabel": { - "revision": 0 - } + "fix": "@php ./vendor/bin/php-cs-fixer fix", + "test": "@php -dzend.assertions=1 -dassert.exception=1 -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text" + }, + "config": { + "allow-plugins": { + "phabel/phabel": false } + } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index e423582..0000000 --- a/composer.lock +++ /dev/null @@ -1,3437 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "665e46a4bc718473c8a6668800c2e003", - "packages": [ - { - "name": "amphp/amp", - "version": "v2.6.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\": "lib" - }, - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "http://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-09-23T18:43:08+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\ByteStream\\": "lib" - }, - "files": [ - "lib/functions.php" - ] - }, - "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": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "amphp/cache", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/cache.git", - "reference": "2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/cache/zipball/2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28", - "reference": "2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/serialization": "^1", - "amphp/sync": "^1.2", - "php": ">=7.1" - }, - "conflict": { - "amphp/file": "<0.2 || >=3" - }, - "require-dev": { - "amphp/file": "^1 || ^2", - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.1", - "phpunit/phpunit": "^6 | ^7 | ^8 | ^9", - "vimeo/psalm": "^4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Cache\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - } - ], - "description": "A promise-aware caching API for Amp.", - "homepage": "https://github.com/amphp/cache", - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/cache/issues", - "source": "https://github.com/amphp/cache/tree/v1.5.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-06-29T17:12:43+00:00" - }, - { - "name": "amphp/dns", - "version": "v1.2.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/dns.git", - "reference": "852292532294d7972c729a96b49756d781f7c59d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/dns/zipball/852292532294d7972c729a96b49756d781f7c59d", - "reference": "852292532294d7972c729a96b49756d781f7c59d", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/byte-stream": "^1.1", - "amphp/cache": "^1.2", - "amphp/parser": "^1", - "amphp/windows-registry": "^0.3", - "daverandom/libdns": "^2.0.1", - "ext-filter": "*", - "ext-json": "*", - "php": ">=7.0" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "phpunit/phpunit": "^6 || ^7 || ^8 || ^9" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Dns\\": "lib" - }, - "files": [ - "lib/functions.php" - ] - }, - "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/v1.2.3" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2020-07-21T19:04:57+00:00" - }, - { - "name": "amphp/parser", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/parser.git", - "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1", - "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1", - "shasum": "" - }, - "require": { - "php": ">=7" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.3", - "phpunit/phpunit": "^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Parser\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.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/is-valid" - }, - "time": "2017-06-06T05:29:10+00:00" - }, - { - "name": "amphp/process", - "version": "v1.1.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/process.git", - "reference": "f09e3ed3b0a953ccbfff1140f12be4a884f0aa83" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/process/zipball/f09e3ed3b0a953ccbfff1140f12be4a884f0aa83", - "reference": "f09e3ed3b0a953ccbfff1140f12be4a884f0aa83", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/byte-stream": "^1.4", - "php": ">=7" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "phpunit/phpunit": "^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Process\\": "lib" - }, - "files": [ - "lib/functions.php" - ] - }, - "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": "Asynchronous process manager.", - "homepage": "https://github.com/amphp/process", - "support": { - "issues": "https://github.com/amphp/process/issues", - "source": "https://github.com/amphp/process/tree/v1.1.3" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-12-17T19:09:33+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": { - "psr-4": { - "Amp\\Serialization\\": "src" - }, - "files": [ - "src/functions.php" - ] - }, - "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": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/socket.git", - "reference": "a8af9f5d0a66c5fe9567da45a51509e592788fe6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/socket/zipball/a8af9f5d0a66c5fe9567da45a51509e592788fe6", - "reference": "a8af9f5d0a66c5fe9567da45a51509e592788fe6", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/byte-stream": "^1.6", - "amphp/dns": "^1 || ^0.9", - "ext-openssl": "*", - "kelunik/certificate": "^1.1", - "league/uri-parser": "^1.4", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "phpunit/phpunit": "^6 || ^7 || ^8", - "vimeo/psalm": "^3.9@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\Socket\\": "src" - }, - "files": [ - "src/functions.php", - "src/Internal/functions.php" - ] - }, - "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": "Async socket connection / server tools for Amp.", - "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/v1.2.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-07-09T18:18:48+00:00" - }, - { - "name": "amphp/sync", - "version": "v1.4.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/sync.git", - "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/sync/zipball/85ab06764f4f36d63b1356b466df6111cf4b89cf", - "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.1", - "phpunit/phpunit": "^9 || ^8 || ^7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Sync\\": "src" - }, - "files": [ - "src/functions.php", - "src/ConcurrentIterator/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Stephen Coakley", - "email": "me@stephencoakley.com" - } - ], - "description": "Mutex, Semaphore, and other synchronization tools for Amp.", - "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/v1.4.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-10-25T18:29:10+00:00" - }, - { - "name": "amphp/windows-registry", - "version": "v0.3.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/windows-registry.git", - "reference": "0f56438b9197e224325e88f305346f0221df1f71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/windows-registry/zipball/0f56438b9197e224325e88f305346f0221df1f71", - "reference": "0f56438b9197e224325e88f305346f0221df1f71", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/byte-stream": "^1.4", - "amphp/process": "^1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\WindowsRegistry\\": "lib" - } - }, - "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/master" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2020-07-10T16:13:29+00:00" - }, - { - "name": "daverandom/libdns", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/DaveRandom/LibDNS.git", - "reference": "e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9", - "reference": "e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": ">=7.0" - }, - "suggest": { - "ext-intl": "Required for IDN support" - }, - "type": "library", - "autoload": { - "psr-4": { - "LibDNS\\": "src/" - }, - "files": [ - "src/functions.php" - ] - }, - "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.0.2" - }, - "time": "2019-12-03T09:12:46+00:00" - }, - { - "name": "kelunik/certificate", - "version": "v1.1.2", - "source": { - "type": "git", - "url": "https://github.com/kelunik/certificate.git", - "reference": "56542e62d51533d04d0a9713261fea546bff80f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kelunik/certificate/zipball/56542e62d51533d04d0a9713261fea546bff80f6", - "reference": "56542e62d51533d04d0a9713261fea546bff80f6", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "php": ">=5.4" - }, - "require-dev": { - "fabpot/php-cs-fixer": "^1.9", - "phpunit/phpunit": "^4.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Kelunik\\Certificate\\": "lib" - } - }, - "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.2" - }, - "time": "2019-05-29T19:02:31+00:00" - }, - { - "name": "league/uri-parser", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri-parser.git", - "reference": "671548427e4c932352d9b9279fdfa345bf63fa00" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-parser/zipball/671548427e4c932352d9b9279fdfa345bf63fa00", - "reference": "671548427e4c932352d9b9279fdfa345bf63fa00", - "shasum": "" - }, - "require": { - "php": ">=7.0.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.0", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpstan/phpstan-strict-rules": "^0.9.0", - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-intl": "Allow parsing RFC3987 compliant hosts", - "league/uri-schemes": "Allow validating and normalizing URI parsing results" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "src" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "userland URI parser RFC 3986 compliant", - "homepage": "https://github.com/thephpleague/uri-parser", - "keywords": [ - "parse_url", - "parser", - "rfc3986", - "rfc3987", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/thephpleague/uri-parser/issues", - "source": "https://github.com/thephpleague/uri-parser/tree/master" - }, - "time": "2018-11-22T07:55:51+00:00" - } - ], - "packages-dev": [ - { - "name": "amphp/file", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/file.git", - "reference": "3d3d084b81a5322d203e11617f7cbe3ea16c40ca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/file/zipball/3d3d084b81a5322d203e11617f7cbe3ea16c40ca", - "reference": "3d3d084b81a5322d203e11617f7cbe3ea16c40ca", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.5.2", - "amphp/byte-stream": "^1.8.1", - "amphp/parallel": "^1.4", - "amphp/sync": "^1.4", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.1", - "ext-eio": "^2 || ^3", - "ext-uv": "^0.3 || ^0.2", - "phpunit/phpunit": "^9 || ^8 || ^7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\File\\": "src" - }, - "files": [ - "src/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Allows non-blocking access to the filesystem for Amp.", - "homepage": "https://github.com/amphp/file", - "keywords": [ - "amp", - "amphp", - "async", - "disk", - "file", - "filesystem", - "io", - "non-blocking", - "static" - ], - "support": { - "issues": "https://github.com/amphp/file/issues", - "source": "https://github.com/amphp/file/tree/v2.0.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-09-20T04:35:03+00:00" - }, - { - "name": "amphp/parallel", - "version": "v1.4.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/parallel.git", - "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/parallel/zipball/fbc128383c1ffb3823866f71b88d8c4722a25ce9", - "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "amphp/byte-stream": "^1.6.1", - "amphp/parser": "^1", - "amphp/process": "^1", - "amphp/serialization": "^1", - "amphp/sync": "^1.0.1", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.1", - "phpunit/phpunit": "^8 || ^7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Parallel\\": "lib" - }, - "files": [ - "lib/Context/functions.php", - "lib/Sync/functions.php", - "lib/Worker/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Stephen Coakley", - "email": "me@stephencoakley.com" - } - ], - "description": "Parallel processing component for Amp.", - "homepage": "https://github.com/amphp/parallel", - "keywords": [ - "async", - "asynchronous", - "concurrent", - "multi-processing", - "multi-threading" - ], - "support": { - "issues": "https://github.com/amphp/parallel/issues", - "source": "https://github.com/amphp/parallel/tree/v1.4.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-10-25T19:16:02+00:00" - }, - { - "name": "amphp/php-cs-fixer-config", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/amphp/php-cs-fixer-config.git", - "reference": "2be2bee66105ace3276c573d41ab71d487bc4b64" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/php-cs-fixer-config/zipball/2be2bee66105ace3276c573d41ab71d487bc4b64", - "reference": "2be2bee66105ace3276c573d41ab71d487bc4b64", - "shasum": "" - }, - "require": { - "friendsofphp/php-cs-fixer": "^2.12", - "php": ">=7.0" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^1.0.2", - "phpunit/phpunit": "^6.0" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\CodeStyle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sascha-Oliver Prolic", - "email": "saschaprolic@googlemail.com" - } - ], - "description": "PHP CS Fixer config for AMP", - "support": { - "issues": "https://github.com/amphp/php-cs-fixer-config/issues", - "source": "https://github.com/amphp/php-cs-fixer-config/tree/master" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-01-11T22:22:36+00:00" - }, - { - "name": "composer/pcre", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/3d322d715c43a1ac36c7fe215fa59336265500f2", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-12-06T15:17:27+00:00" - }, - { - "name": "composer/semver", - "version": "3.2.6", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "83e511e247de329283478496f7a1e114c9517506" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506", - "reference": "83e511e247de329283478496f7a1e114c9517506", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.6" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-10-25T11:34:17+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6555461e76962fd0379c444c46fd558a0fcfb65e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6555461e76962fd0379c444c46fd558a0fcfb65e", - "reference": "6555461e76962fd0379c444c46fd558a0fcfb65e", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-12-08T13:07:32+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.13.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.2" - }, - "time": "2021-08-05T19:00:23+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^8.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2020-05-25T17:44:05+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v2.19.3", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", - "shasum": "" - }, - "require": { - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.2 || ^2.0", - "doctrine/annotations": "^1.2", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", - "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0", - "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0 || ^5.0", - "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.4", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4.2", - "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", - "symfony/phpunit-bridge": "^5.2.1", - "symfony/yaml": "^3.0 || ^4.0 || ^5.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters.", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "extra": { - "branch-alias": { - "dev-master": "2.19-dev" - } - }, - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, - "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/Test/IsIdenticalConstraint.php", - "tests/Test/TokensWithObservedTransformers.php", - "tests/TestCase.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz RumiƄski", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.3" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2021-11-15T17:17:55+00:00" - }, - { - "name": "phabel/phabel", - "version": "1.0.49.80", - "source": { - "type": "git", - "url": "https://github.com/phabelio/phabel.git", - "reference": "304d17d26a42d0922e6c2dd2576aaf2944e1c2d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phabelio/phabel/zipball/304d17d26a42d0922e6c2dd2576aaf2944e1c2d1", - "reference": "304d17d26a42d0922e6c2dd2576aaf2944e1c2d1", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=8.0" - }, - "provide": { - "phabelio/phabel": "self.version" - }, - "require-dev": { - "amphp/file": "^2.0", - "bamarni/composer-bin-plugin": "^1.4" - }, - "bin": [ - "bin/phabel" - ], - "type": "composer-plugin", - "extra": { - "class": "Phabel\\Composer\\Plugin", - "plugin-modifies-downloads": true - }, - "autoload": { - "psr-4": { - "Phabel\\": "src", - "PhabelVendor\\Amp\\": [ - "vendor-bundle/amphp/amp/lib" - ], - "PhabelVendor\\Amp\\ByteStream\\": [ - "vendor-bundle/amphp/byte-stream/lib" - ], - "PhabelVendor\\Amp\\Parallel\\": [ - "vendor-bundle/amphp/parallel/lib" - ], - "PhabelVendor\\Amp\\Parser\\": [ - "vendor-bundle/amphp/parser/lib" - ], - "PhabelVendor\\Amp\\Process\\": [ - "vendor-bundle/amphp/process/lib" - ], - "PhabelVendor\\Amp\\Serialization\\": [ - "vendor-bundle/amphp/serialization/src" - ], - "PhabelVendor\\Amp\\Sync\\": [ - "vendor-bundle/amphp/sync/src" - ], - "PhabelVendor\\PhpParser\\": [ - "vendor-bundle/phabel/php-parser/lib/PhpParser" - ], - "PhabelVendor\\PHPStan\\PhpDocParser\\": [ - "vendor-bundle/phpstan/phpdoc-parser/src/" - ], - "PhabelVendor\\Psr\\Container\\": [ - "vendor-bundle/psr/container/src/" - ], - "PhabelVendor\\Psr\\Log\\": [ - "vendor-bundle/psr/log/Psr/Log/" - ], - "PhabelVendor\\Symfony\\Component\\Console\\": [ - "vendor-bundle/symfony/console/" - ], - "Symfony\\Polyfill\\Ctype\\": [ - "vendor-bundle/symfony/polyfill-ctype/" - ], - "Symfony\\Polyfill\\Intl\\Grapheme\\": [ - "vendor-bundle/symfony/polyfill-intl-grapheme/" - ], - "Symfony\\Polyfill\\Intl\\Normalizer\\": [ - "vendor-bundle/symfony/polyfill-intl-normalizer/" - ], - "Symfony\\Polyfill\\Mbstring\\": [ - "vendor-bundle/symfony/polyfill-mbstring/" - ], - "Symfony\\Polyfill\\Php73\\": [ - "vendor-bundle/symfony/polyfill-php73/" - ], - "Symfony\\Polyfill\\Php80\\": [ - "vendor-bundle/symfony/polyfill-php80/" - ], - "PhabelVendor\\Symfony\\Component\\Process\\": [ - "vendor-bundle/symfony/process/" - ], - "PhabelVendor\\Symfony\\Contracts\\Service\\": [ - "vendor-bundle/symfony/service-contracts/" - ], - "PhabelVendor\\Symfony\\Component\\String\\": [ - "vendor-bundle/symfony/string/" - ] - }, - "files": [ - "src/guard.php", - "vendor-bundle/amphp/amp/lib/functions.php", - "vendor-bundle/amphp/amp/lib/Internal/functions.php", - "vendor-bundle/amphp/byte-stream/lib/functions.php", - "vendor-bundle/amphp/parallel/lib/Context/functions.php", - "vendor-bundle/amphp/parallel/lib/Sync/functions.php", - "vendor-bundle/amphp/parallel/lib/Worker/functions.php", - "vendor-bundle/amphp/process/lib/functions.php", - "vendor-bundle/amphp/serialization/src/functions.php", - "vendor-bundle/amphp/sync/src/functions.php", - "vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.php", - "vendor-bundle/symfony/deprecation-contracts/function.php", - "vendor-bundle/symfony/polyfill-ctype/bootstrap.php", - "vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.php", - "vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.php", - "vendor-bundle/symfony/polyfill-mbstring/bootstrap.php", - "vendor-bundle/symfony/polyfill-php73/bootstrap.php", - "vendor-bundle/symfony/polyfill-php80/bootstrap.php", - "vendor-bundle/symfony/string/Resources/functions.php" - ], - "classmap": [ - "vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs", - "vendor-bundle/symfony/polyfill-php73/Resources/stubs", - "vendor-bundle/symfony/polyfill-php80/Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniil Gentili", - "email": "daniil@daniil.it" - } - ], - "description": "Write and deploy modern PHP 8 code, today.", - "support": { - "issues": "https://github.com/phabelio/phabel/issues", - "source": "https://github.com/phabelio/phabel/tree/1.0.49.80" - }, - "funding": [ - { - "url": "https://github.com/danog", - "type": "github" - } - ], - "time": "2021-12-22T13:38:59+00:00" - }, - { - "name": "php-cs-fixer/diff", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "SpacePossum" - } - ], - "description": "sebastian/diff v2 backport support for PHP5.6", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" - }, - "time": "2020-10-14T08:39:05+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/2.0.0" - }, - "time": "2021-07-14T16:41:46+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a2c6b7ced2eb7799a35375fb9022519282b5405e", - "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "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": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.2" - }, - "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": "2021-12-20T16:11:12+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", - "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", - "shasum": "" - }, - "require": { - "php": ">=8.0.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0" - }, - "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": "2021-11-01T23:48:49+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "27d39ae126352b9fa3be5e196ccf4617897be3eb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/27d39ae126352b9fa3be5e196ccf4617897be3eb", - "reference": "27d39ae126352b9fa3be5e196ccf4617897be3eb", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "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": "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/v5.4.0" - }, - "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": "2021-11-23T10:19:22+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "aa5422287b75594b90ee9cd807caf8f0df491385" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/aa5422287b75594b90ee9cd807caf8f0df491385", - "reference": "aa5422287b75594b90ee9cd807caf8f0df491385", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.0" - }, - "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": "2021-07-15T12:33:35+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/731f917dc31edcffec2c6a777f3698c33bea8f01", - "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "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": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.0" - }, - "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": "2021-10-28T13:39:27+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "e77046c252be48c48a40816187ed527703c8f76c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e77046c252be48c48a40816187ed527703c8f76c", - "reference": "e77046c252be48c48a40816187ed527703c8f76c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "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": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.2" - }, - "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": "2021-12-15T11:06:13+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "b0fb78576487af19c500aaddb269fd36701d4847" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b0fb78576487af19c500aaddb269fd36701d4847", - "reference": "b0fb78576487af19c500aaddb269fd36701d4847", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "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": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.0" - }, - "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": "2021-11-23T10:19:22+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" - }, - "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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.23.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "16880ba9c5ebe3642d1995ab866db29270b36535" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535", - "reference": "16880ba9c5ebe3642d1995ab866db29270b36535", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1" - }, - "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": "2021-05-27T12:26:48+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" - }, - "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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.23.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" - }, - "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": "2021-05-27T12:26:48+00:00" - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" - }, - "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": "2020-10-23T14:02:19+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0" - }, - "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": "2021-05-27T09:17:38+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", - "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" - }, - "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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.23.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", - "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" - }, - "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": "2021-07-28T13:41:28+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", - "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "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/v5.4.2" - }, - "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": "2021-12-27T21:01:00+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/36715ebf9fb9db73db0cb24263c79077c6fe8603", - "reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.0" - }, - "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": "2021-11-04T17:53:12+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "208ef96122bfed82a8f3a61458a07113a08bdcfe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/208ef96122bfed82a8f3a61458a07113a08bdcfe", - "reference": "208ef96122bfed82a8f3a61458a07113a08bdcfe", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "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": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.0" - }, - "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": "2021-11-23T10:19:22+00:00" - }, - { - "name": "symfony/string", - "version": "v6.0.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "bae261d0c3ac38a1f802b4dfed42094296100631" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/bae261d0c3ac38a1f802b4dfed42094296100631", - "reference": "bae261d0c3ac38a1f802b4dfed42094296100631", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.0" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "files": [ - "Resources/functions.php" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.0.2" - }, - "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": "2021-12-16T22:13:01+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "amphp/php-cs-fixer-config": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^8.0", - "ext-sockets": "*" - }, - "platform-dev": [], - "plugin-api-version": "2.2.0" -} diff --git a/examples/scan.php b/examples/scan.php index 673a4c7..0b7ac6d 100644 --- a/examples/scan.php +++ b/examples/scan.php @@ -1,21 +1,18 @@ -close(); // always close files to avoid memory leaks - echo (string) $res . PHP_EOL; -}); +/** @var \Amp\ClamAV\ScanResult */ +$res = ClamAV\scanFromStream($file); +$file->close(); // always close files to avoid memory leaks +echo (string) $res . PHP_EOL; diff --git a/lib/Base.php b/lib/Base.php index 9204b36..eb2db9f 100644 --- a/lib/Base.php +++ b/lib/Base.php @@ -1,95 +1,67 @@ - */ - public function ping(): Promise + public function ping(): bool { - return call(function (): \Generator { - return 'PONG' === yield from $this->command('PING'); - }); + return 'PONG' === $this->command('PING'); } /** - * Scans a file or directory using the native ClamD `SCAN` command (ClamD must have access to this file!) - * + * Scans a file or directory using the native ClamD `SCAN` command (ClamD must have access to this file!). + * * Stops once a malware has been found. * - * @param string $path * - * @return Promise */ - public function scan(string $path): Promise + public function scan(string $path): ScanResult { - return call(function () use ($path): \Generator { - return $this->parseScanOutput(yield from $this->command('SCAN ' . $path)); - }); + return $this->parseScanOutput($this->command('SCAN ' . $path)); } /** - * Runs a continue scan that stops after the entire file has been checked - * - * @param string $path - * - * @return Promise - */ - public function continueScan(string $path): Promise - { - return call(function () use ($path) { - $output = \trim(yield from $this->command('CONTSCAN ' . $path)); - return \array_map([$this, 'parseScanOutput'], array_filter(explode("\n", $output), fn ($val) => !empty($val))); - }); - } - - /** - * Runs the `VERSION` command - * - * @return Promise + * Runs the `VERSION` command. + * + * @return string */ public function version() { - return call(function () { - return \trim(yield from $this->command('VERSION')); - }); + return \trim($this->command('VERSION')); } /** * Scans from a stream. * - * @param $stream * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult> - * @throws \Amp\ClamAV\ClamException If an exception happens with writing to the stream (if the INSTREAM limit has been reached, the errorCode will be `ClamException::INSTREAM_WRITE_EXCEEDED`) + * @throws \Amp\ClamAV\ClamException May happen while writing to the stream (if the INSTREAM limit has been reached, the errorCode will be `ClamException::INSTREAM_WRITE_EXCEEDED`) * @throws \Amp\ByteStream\ClosedException If the socket has been closed */ - abstract public function scanFromStream(InputStream $stream): Promise; + abstract public function scanFromStream(ReadableStream $stream): ScanResult; /** * Pipes an InputStream to a ClamD socket by using the `INSTREAM` command. * - * @param \Amp\ByteStream\InputStream $stream The stream to pipe + * @param \Amp\ByteStream\ReadableStream $stream The stream to pipe * @param \Amp\Socket\Socket $socket The destination socket * - * @return \Generator * @throws \Amp\ByteStream\ClosedException If the socket has been closed * @throws \Amp\ByteStream\StreamException If the writing fails */ - protected function pipeStreamScan(InputStream $stream, Socket $socket): \Generator + protected function pipeStreamScan(ReadableStream $stream, Socket $socket): void { - yield $socket->write("zINSTREAM\x0"); - while (null !== $chunk = yield $stream->read()) { + $socket->write("zINSTREAM\x0"); + while (null !== $chunk = $stream->read()) { if (empty($chunk)) { continue; } @@ -101,10 +73,30 @@ protected function pipeStreamScan(InputStream $stream, Socket $socket): \Generat // pack the chunk length $lengthData = \pack('N', \strlen($chunk)); - yield $socket->write($lengthData . $chunk); + $socket->write($lengthData . $chunk); $chunk = null; } - yield $socket->write(\pack('N', 0)); + $socket->write(\pack('N', 0)); + } + + /** + * Handles a [StreamException] as a result of [pipeStreamScan] after a + * [scanFromStream] call. + * + * @codeCoverageIgnore + * @throws \Amp\ClamAV\ClamException + */ + protected function handleStreamException(StreamException $e, ?string $message): void + { + if ($message != null) { + if (\str_starts_with($message, 'INSTREAM size limit exceeded')) { + throw new ClamException('INSTREAM size limit exceeded', ClamException::INSTREAM_WRITE_EXCEEDED, $e); + } + + throw new ClamException($message, ClamException::UNKNOWN, $e); + } + + throw new ClamException($e->getMessage(), ClamException::UNKNOWN, $e); } /** @@ -112,7 +104,6 @@ protected function pipeStreamScan(InputStream $stream, Socket $socket): \Generat * * @param string $output The unparsed output * - * @return \Amp\ClamAV\ScanResult * @throws \Amp\ClamAV\ClamException * @throws \Amp\ClamAV\ParseException */ @@ -120,6 +111,9 @@ protected function parseScanOutput(string $output): ScanResult { $output = \trim($output); $separatorPos = \strrpos($output, ': '); + if ($separatorPos === false) { + throw new ParseException('Could not parse string: ' . $output); + } $separatorLength = 2; $filename = \substr($output, 0, $separatorPos); $result = \substr($output, $separatorPos + $separatorLength); @@ -152,7 +146,7 @@ protected function parseScanOutput(string $output): ScanResult * @param string $command The command to execute * @param bool $waitForResponse Wait for the response * - * @return \Generator + * @return ?string */ - abstract protected function command(string $command, bool $waitForResponse = true): \Generator; + abstract protected function command(string $command, bool $waitForResponse = true): ?string; } diff --git a/lib/ClamAV.php b/lib/ClamAV.php index afadbd5..0d38e6b 100644 --- a/lib/ClamAV.php +++ b/lib/ClamAV.php @@ -1,11 +1,10 @@ - */ - public function session(): Promise + public function session(): Session { - return call(function () { - /** @var Socket */ - $socket = yield \Amp\Socket\connect($this->sockuri); + /** @var Socket */ + $socket = \Amp\Socket\connect($this->sockuri); + + return Session::fromSocket($socket); + } - return yield Session::fromSocket($socket); - }); + /** + * Runs a continue scan that stops after the entire file has been checked. + * + * + * @return ScanResult[] + */ + public function continueScan(string $path): array + { + $output = \trim($this->command('CONTSCAN ' . $path)); + return \array_map([$this, 'parseScanOutput'], \array_filter(\explode("\n", $output), fn ($val) => !empty($val))); } /** @@ -43,54 +51,40 @@ public function session(): Promise * * @param string $path The file or directory's path * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult> */ - public function multiScan(string $path): Promise + public function multiScan(string $path): ScanResult { - return call(function () use ($path) { - return $this->parseScanOutput(yield from $this->command('MULTISCAN ' . $path)); - }); + return $this->parseScanOutput($this->command('MULTISCAN ' . $path)); } /** @inheritdoc */ - public function scanFromStream(InputStream $stream): Promise + public function scanFromStream(ReadableStream $stream): ScanResult { - return call(function () use ($stream) { - /** @var Socket */ - $socket = yield from $this->getSocket(); - try { - yield from $this->pipeStreamScan($stream, $socket); - } catch (StreamException $e) { - if (!$socket->isClosed()) { - $message = yield $socket->read(); - if ($message === 'INSTREAM size limit exceeded') { - throw new ClamException('INSTREAM size limit exceeded', ClamException::INSTREAM_WRITE_EXCEEDED, $e); - } - } - throw new ClamException($e->getMessage() . $message, ClamException::UNKNOWN, $e); - } - return $this->parseScanOutput(yield $socket->read()); - }); + $socket = $this->getSocket(); + try { + $this->pipeStreamScan($stream, $socket); + } catch (StreamException $e) { + $this->handleStreamException($e, $socket->isClosed() ? null : $socket->read()); + } + return $this->parseScanOutput($socket->read()); } /** @inheritdoc */ - protected function command(string $command, bool $waitForResponse = true): \Generator + protected function command(string $command, bool $waitForResponse = true): ?string { - /** @var Socket */ - $socket = yield from $this->getSocket(); - yield $socket->write('z' . $command . "\x0"); + $socket = $this->getSocket(); + $socket->write('z' . $command . "\x0"); if ($waitForResponse) { - return \trim(yield $socket->read()); + return \trim($socket->read()); } } /** * Gets a new socket (to execute a new command). * - * @return \Generator<\Amp\Socket> */ - protected function getSocket(): \Generator + protected function getSocket(): Socket { - return yield \Amp\Socket\connect($this->sockuri); + return \Amp\Socket\connect($this->sockuri); } } diff --git a/lib/ClamException.php b/lib/ClamException.php index 55a4c3d..379cbac 100644 --- a/lib/ClamException.php +++ b/lib/ClamException.php @@ -1,12 +1,12 @@ -filename, true) . ', isInfected: ' . \var_export($this->isInfected, true) . ', malwareType: ' . \var_export($this->malwareType, true) . ')'; } + + public function equals(ScanResult $other): bool + { + return $this->isInfected == $other->isInfected && + $this->filename == $other->filename && + $this->malwareType == $other->malwareType; + } } diff --git a/lib/Session.php b/lib/Session.php index 1f9b38c..40991d9 100644 --- a/lib/Session.php +++ b/lib/Session.php @@ -1,19 +1,20 @@ - \Amp\Deferred + private array $deferreds = []; // $i -> \Amp\DeferredFuture private int $reqId = 1; private function __construct() @@ -25,28 +26,26 @@ private function __construct() * * @internal * - * @param \Amp\Socket\Socket $socket * - * @return Promise */ - public static function fromSocket(Socket $socket): Promise + public static function fromSocket(Socket $socket): self { - return call(function () use ($socket) { - $instance = new self; - $instance->socket = $socket; - yield from $instance->command('IDSESSION', waitForResponse: false); - $instance->readLoop(); - return $instance; - }); + $instance = new self; + $instance->socket = $socket; + $instance->command('IDSESSION', waitForResponse: false); + $instance->readLoop(); + return $instance; } /** @inheritdoc */ - protected function command(string $command, bool $waitForResponse = true): \Generator + protected function command(string $command, bool $waitForResponse = true): ?string { - yield $this->socket->write('z' . $command . "\x0"); + $this->socket->write('z' . $command . "\x0"); if ($waitForResponse) { - return yield $this->commandResponsePromise($this->reqId++); + return $this->commandResponseFuture($this->reqId++)->await(); } + + return null; } /** @@ -54,38 +53,38 @@ protected function command(string $command, bool $waitForResponse = true): \Gene * * @param int $reqId The request's id (an auto-increment integer, which will be used by ClamD to identify this request) * - * @return \Amp\Promise + * @return \Amp\Future */ - protected function commandResponsePromise(int $reqId): Promise + protected function commandResponseFuture(int $reqId): Future { if (isset($this->deferreds[$reqId])) { return $this->deferreds[$reqId]; } - $deferred = new Deferred; + $deferred = new DeferredFuture; $this->deferreds[$reqId] = $deferred; - return $deferred->promise(); + return $deferred->getFuture(); } /** * A read loop for the ClamD socket (given that it might send responses unordered). * - * @return \Amp\Promise + * @return \Amp\Future */ protected function readLoop() { - return call(function () { + return async(function () { $chunk = ''; // read from the socket - while (null !== $chunk = yield $this->socket->read()) { + while (null !== $chunk = $this->socket->read()) { // split the message (ex: "1: PONG") $parts = \explode(' ', $chunk, 2); $message = \trim($parts[1]); $id = (int) \substr($parts[0], 0, \strpos($parts[0], ':')); if (isset($this->deferreds[$id])) { - /** @var Deferred */ + /** @var DeferredFuture */ $deferred = $this->deferreds[$id]; // resolve the enqueued request - $deferred->resolve($message); + $deferred->complete($message); unset($this->deferreds[$id]); } } @@ -95,33 +94,26 @@ protected function readLoop() /** * Ends this session. * - * @return \Amp\Promise */ - public function end(): Promise + public function end(): void { - return call(function () { - yield from $this->command('END', waitForResponse: false); - yield $this->socket->end(); - }); + $this->command('END', waitForResponse: false); + $this->socket->end(); } /** @inheritdoc */ - public function scanFromStream(InputStream $stream): Promise + public function scanFromStream(ReadableStream $stream): ScanResult { - return call(function () use ($stream) { - $promise = $this->commandResponsePromise($this->reqId++); - try { - yield from $this->pipeStreamScan($stream, $this->socket); - } catch (StreamException $e) { - if (!$this->socket->isClosed()) { - $message = yield $promise; - if ($message === 'INSTREAM size limit exceeded') { - throw new ClamException('INSTREAM size limit exceeded', ClamException::INSTREAM_WRITE_EXCEEDED, $e); - } - } - throw new ClamException($e->getMessage() . $message, ClamException::UNKNOWN, $e); - } - return $this->parseScanOutput(yield $promise); - }); + $future = $this->commandResponseFuture($this->reqId++); + try { + $this->pipeStreamScan($stream, $this->socket); + } catch (StreamException $e) { + $this->handleStreamException( + $e, + $this->socket->isClosed() ? null : $future->await(), + ); + } + + return $this->parseScanOutput($future->await()); } } diff --git a/lib/functions.php b/lib/functions.php index d8635f7..b9f96d1 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -1,51 +1,44 @@ - */ -function ping(): Promise +function ping(): bool { return clamav()->ping(); } /** - * Scans a file or directory using the native ClamD `SCAN` command (ClamD must have access to this file!) - * + * Scans a file or directory using the native ClamD `SCAN` command (ClamD must have access to this file!). + * * Stops once a malware has been found. * - * @param string $path * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult> */ -function scan(string $path): Promise +function scan(string $path): ScanResult { return clamav()->scan($path); } @@ -55,31 +48,28 @@ function scan(string $path): Promise * * @param string $path The file or directory's path * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult> */ -function multiScan(string $path): Promise +function multiScan(string $path): ScanResult { return clamav()->multiScan($path); } /** - * Runs a continue scan that stops after the entire file has been checked - * - * @param string $path - * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult[]> + * Runs a continue scan that stops after the entire file has been checked. + * + * + * @return \Amp\ClamAV\ScanResult[] */ -function continueScan(string $path) +function continueScan(string $path): array { return clamav()->continueScan($path); } /** - * Runs the `VERSION` command - * - * @return \Amp\Promise + * Runs the `VERSION` command. + * */ -function version(): Promise +function version(): string { return clamav()->version(); } @@ -87,13 +77,11 @@ function version(): Promise /** * Scans from a stream. * - * @param $stream * - * @return \Amp\Promise<\Amp\ClamAV\ScanResult> - * @throws \Amp\ClamAV\ClamException If an exception happens with writing to the stream (if the INSTREAM limit has been reached, the errorCode will be `ClamException::INSTREAM_WRITE_EXCEEDED`) + * @throws \Amp\ClamAV\ClamException May happen while writing to the stream (if the INSTREAM limit has been reached, the errorCode will be `ClamException::INSTREAM_WRITE_EXCEEDED`) * @throws \Amp\ByteStream\ClosedException If the socket has been closed */ -function scanFromStream(InputStream $stream): Promise +function scanFromStream(ReadableStream $stream): ScanResult { return clamav()->scanFromStream($stream); } @@ -102,9 +90,8 @@ function scanFromStream(InputStream $stream): Promise * Initiates a new ClamAV session * Note: you MUST call `Session::end()` once you are done. * - * @return \Amp\Promise<\Amp\ClamAV\Session> */ -function session(): Promise +function session(): Session { return clamav()->session(); } diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..4d176fc --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ + + + + + tests + tests/ClamAVErrorTest.php + + + + + lib + + + diff --git a/tests/ClamAVErrorTest.php b/tests/ClamAVErrorTest.php new file mode 100644 index 0000000..8a8d360 --- /dev/null +++ b/tests/ClamAVErrorTest.php @@ -0,0 +1,38 @@ +expectException(ClamException::class); + $this->expectExceptionCode(ClamException::INSTREAM_WRITE_EXCEEDED); + $this->expectExceptionMessage('INSTREAM size limit exceeded'); + + $stream = \Amp\File\openFile('/dev/zero', 'r'); + scanFromStream($stream); + } + + // public function testTimeout(): void + // { + // $this->expectException(ClamException::class); + // $this->expectExceptionCode(ClamException::TIMEOUT); + // $this->expectExceptionMessage('timeout'); + // + // // to get this error, we're gonna provide a stream which never outputs any data + // $stream = new \Amp\ByteStream\ReadableIterableStream((function() { + // // a 300s delay should trigger a TIMEOUT? + // delay(300); + // yield ''; + // })()); + // + // scanFromStream($stream); + // } + +} diff --git a/tests/ClamAVTest.php b/tests/ClamAVTest.php new file mode 100644 index 0000000..db2a310 --- /dev/null +++ b/tests/ClamAVTest.php @@ -0,0 +1,86 @@ +assertTrue(\Amp\File\exists($target)); + + $session = session(); + + $copyTarget = $this->copyTmp($target); + $shouldBe = new ScanResult( + $copyTarget, + $assertIsInfected, + $assertMalwareType + ); + $scan = scan($copyTarget); + $scan2 = multiScan($copyTarget); + $scan3 = $session->scan($copyTarget); + $this->assertObjectEquals($scan, $shouldBe); + $this->assertObjectEquals($scan2, $shouldBe); + $this->assertObjectEquals($scan3, $shouldBe); + + $scan4 = continueScan($copyTarget); + $this->assertSame(\count($scan4), 1); + $this->assertObjectEquals($scan4[0], $shouldBe); + \Amp\File\deleteFile($copyTarget); + + // try stream scan + $shouldBe = new ScanResult( + 'stream', + $assertIsInfected, + $assertMalwareType + ); + $file = \Amp\File\openFile($target, 'r'); + $scan = scanFromStream($file); + // reset stream position + $file->seek(0); + $scan2 = $session->scanFromStream($file); + $this->assertObjectEquals($scan, $shouldBe); + $this->assertObjectEquals($scan2, $shouldBe); + $file->close(); + $session->end(); + } + + public function test(): void + { + $this->assertTrue(ping()); + + echo 'TEST RUNNING ON CLAMAV: ' . version() . PHP_EOL; + } + + public function testEicar(): void + { + $target = __DIR__ . '/eicar.com'; + $this->runTestOn( + target: $target, + assertIsInfected: true, + assertMalwareType: 'Win.Test.EICAR_HDB-1' + ); + } + + public function testNormalFile(): void + { + $target = __DIR__ . '/harmless.txt'; + $this->runTestOn( + target: $target, + assertIsInfected: false, + assertMalwareType: null + ); + } +} diff --git a/tests/eicar.com b/tests/eicar.com new file mode 100755 index 0000000..a2463df --- /dev/null +++ b/tests/eicar.com @@ -0,0 +1 @@ +X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* \ No newline at end of file diff --git a/tests/harmless.txt b/tests/harmless.txt new file mode 100644 index 0000000..c7c7da3 --- /dev/null +++ b/tests/harmless.txt @@ -0,0 +1 @@ +hello there