From bdbb5703549bcd7c73775305666f06fb3c08dc5d Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 14:47:48 +0545 Subject: [PATCH 01/11] chore: raise PHP baseline and add PSR HTTP + PHPUnit --- composer.json | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index b14e49a..ecdcabd 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,41 @@ { - "name":"sudiptpa/ipstack", - "type":"library", - "description":"A simple package for IP to Location implementation with PHP.", - "keywords":[ + "name": "sudiptpa/ipstack", + "type": "library", + "description": "A simple package for IP to Location implementation with PHP.", + "keywords": [ "geoip", "ipstack", "ip to location" ], - "license":"MIT", - "authors":[ + "license": "MIT", + "authors": [ { - "name":"Sujip Thapa", - "email":"sudiptpa@gmail.com" + "name": "Sujip Thapa", + "email": "sudiptpa@gmail.com" } ], - "require":{ - "php": "~7.0" + "require": { + "php": "^8.1", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" }, - "require-dev":{ - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "~6.0", - "squizlabs/php_codesniffer": "^3", - "phpro/grumphp": "^0.14.0" + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "extra":{ - "branch-alias":{ - "dev-master":"1.0.x-dev" + "autoload": { + "psr-4": { + "Sujip\\Ipstack\\": "src/" } }, - "autoload":{ - "psr-4":{ - "Sujip\\Ipstack\\":"src/" + "autoload-dev": { + "psr-4": { + "Sujip\\Ipstack\\Tests\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" } }, "scripts": { @@ -39,4 +44,4 @@ "fix-style": "phpcbf -p --standard=PSR2 src/" }, "prefer-stable": true -} +} \ No newline at end of file From c76cc7f55e5c0db977e8d68af87e2de23dc4bd8b Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 15:47:45 +0545 Subject: [PATCH 02/11] Adding a lot of new architecture codebase. --- .github/workflows/ci.yml | 29 + .phpunit.cache/test-results | 1 + .travis.yml | 11 - composer.json | 23 +- composer.lock | 3169 ++++++++------------ phpstan.neon | 5 + phpunit.xml | 8 + src/Client/Config.php | 13 + src/Client/Endpoint.php | 28 + src/Client/IpstackClient.php | 90 + src/Client/Options.php | 47 + src/Exception/ApiErrorException.php | 15 + src/Exception/Forbidden.php | 20 - src/Exception/InvalidResponseException.php | 7 + src/Exception/IpstackException.php | 7 + src/Exception/TransportException.php | 7 + src/Factory/IpstackFactory.php | 65 + src/Http/Request.php | 77 - src/Http/Response.php | 30 - src/Ipstack.php | 274 +- src/Mapper/IpstackResultMapper.php | 117 + src/Model/Attributes/MapFrom.php | 11 + src/Model/Connection.php | 22 + src/Model/Country.php | 17 + src/Model/IpstackResult.php | 47 + src/Model/Location.php | 16 + src/Model/Region.php | 15 + src/Model/Routing.php | 16 + src/Model/Security.php | 21 + src/Transport/Psr18Transport.php | 43 + src/Transport/TransportInterface.php | 11 + tests/Fakes/FakeTransport.php | 24 + tests/IpstackClientTest.php | 72 + tests/IpstackTest.php | 49 - tests/Mock/Response/response.json | 59 - 35 files changed, 2023 insertions(+), 2443 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .phpunit.cache/test-results delete mode 100644 .travis.yml create mode 100644 phpstan.neon create mode 100644 phpunit.xml create mode 100644 src/Client/Config.php create mode 100644 src/Client/Endpoint.php create mode 100644 src/Client/IpstackClient.php create mode 100644 src/Client/Options.php create mode 100644 src/Exception/ApiErrorException.php delete mode 100644 src/Exception/Forbidden.php create mode 100644 src/Exception/InvalidResponseException.php create mode 100644 src/Exception/IpstackException.php create mode 100644 src/Exception/TransportException.php create mode 100644 src/Factory/IpstackFactory.php delete mode 100644 src/Http/Request.php delete mode 100644 src/Http/Response.php create mode 100644 src/Mapper/IpstackResultMapper.php create mode 100644 src/Model/Attributes/MapFrom.php create mode 100644 src/Model/Connection.php create mode 100644 src/Model/Country.php create mode 100644 src/Model/IpstackResult.php create mode 100644 src/Model/Location.php create mode 100644 src/Model/Region.php create mode 100644 src/Model/Routing.php create mode 100644 src/Model/Security.php create mode 100644 src/Transport/Psr18Transport.php create mode 100644 src/Transport/TransportInterface.php create mode 100644 tests/Fakes/FakeTransport.php create mode 100644 tests/IpstackClientTest.php delete mode 100644 tests/IpstackTest.php delete mode 100644 tests/Mock/Response/response.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0b8d4ae --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +on: + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + php: ['8.5'] + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run tests + run: composer test + + - name: Run PHPStan + run: composer stan \ No newline at end of file diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results new file mode 100644 index 0000000..55b4b08 --- /dev/null +++ b/.phpunit.cache/test-results @@ -0,0 +1 @@ +{"version":2,"defects":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":8},"times":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":0.004,"Ipstack\\Tests\\IpstackClientTest::testApiErrorThrows":0.001}} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5c82401..0000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: php - -php: - - '7.0' - - '7.1' - - '7.2' - -before_script: - - composer install -n --dev --prefer-source - -script: vendor/bin/phpcs -p --standard=PSR2 src/ && vendor/bin/phpunit diff --git a/composer.json b/composer.json index ecdcabd..2dc7582 100644 --- a/composer.json +++ b/composer.json @@ -15,22 +15,25 @@ } ], "require": { - "php": "^8.1", + "php": "^8.5", "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0" + "psr/http-factory": "^1.1", + "psr/http-message": "^2.0", + "symfony/http-client": "^8.0", + "nyholm/psr7": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0", + "phpstan/phpstan": "^1.11" }, "autoload": { "psr-4": { - "Sujip\\Ipstack\\": "src/" + "Ipstack\\": "src/" } }, "autoload-dev": { "psr-4": { - "Sujip\\Ipstack\\Tests\\": "tests/" + "Ipstack\\Tests\\": "tests/" } }, "extra": { @@ -39,9 +42,9 @@ } }, "scripts": { - "test": "vendor/bin/phpunit", - "check-style": "phpcs -p --standard=PSR2 src/", - "fix-style": "phpcbf -p --standard=PSR2 src/" + "test": "phpunit", + "stan": "phpstan analyse -c phpstan.neon" }, + "minimum-stability": "stable", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index fd18a7c..f4731e2 100755 --- a/composer.lock +++ b/composer.lock @@ -4,42 +4,48 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7d1da35e8f2d8380766e0d8bea6b84d6", - "packages": [], - "packages-dev": [ + "content-hash": "839833b42a617ccf1654a6ed7efc216b", + "packages": [ { - "name": "composer/ca-bundle", - "version": "1.1.1", + "name": "nyholm/psr7", + "version": "1.8.2", "source": { "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169" + "url": "https://github.com/Nyholm/psr7.git", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/d2c0a83b7533d6912e8d516756ebd34f893e9169", - "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", "shasum": "" }, "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0" + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", - "psr/log": "^1.0", - "symfony/process": "^2.5 || ^3.0 || ^4.0" + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.8-dev" } }, "autoload": { "psr-4": { - "Composer\\CaBundle\\": "src" + "Nyholm\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -48,74 +54,62 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" } ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } ], - "time": "2018-03-29T19:57:20+00:00" + "time": "2024-09-09T07:06:30+00:00" }, { - "name": "composer/composer", - "version": "1.6.5", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/composer/composer.git", - "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/b184a92419cc9a9c4c6a09db555a94d441cb11c9", - "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "composer/ca-bundle": "^1.0", - "composer/semver": "^1.0", - "composer/spdx-licenses": "^1.2", - "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0", - "seld/cli-prompt": "^1.0", - "seld/jsonlint": "^1.4", - "seld/phar-utils": "^1.0", - "symfony/console": "^2.7 || ^3.0 || ^4.0", - "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", - "symfony/finder": "^2.7 || ^3.0 || ^4.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0" - }, - "conflict": { - "symfony/console": "2.8.38" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7", - "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" - }, - "suggest": { - "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", - "ext-zip": "Enabling the zip extension allows you to unzip archives", - "ext-zlib": "Allow gzip compression of HTTP requests" + "php": ">=7.4.0" }, - "bin": [ - "bin/composer" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Composer\\": "src/Composer" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -124,55 +118,52 @@ ], "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": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.", - "homepage": "https://getcomposer.org/", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "autoload", - "dependency", - "package" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2018-05-04T09:44:59+00:00" + "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": "composer/semver", - "version": "1.4.2", + "name": "psr/http-client", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -181,60 +172,50 @@ ], "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" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "http", + "http-client", + "psr", + "psr-18" ], - "time": "2016-08-30T16:08:34+00:00" + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" }, { - "name": "composer/spdx-licenses", - "version": "1.4.0", + "name": "psr/http-factory", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/composer/spdx-licenses.git", - "reference": "cb17687e9f936acd7e7245ad3890f953770dec1b" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/cb17687e9f936acd7e7245ad3890f953770dec1b", - "reference": "cb17687e9f936acd7e7245ad3890f953770dec1b", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Composer\\Spdx\\": "src" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -243,59 +224,52 @@ ], "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" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "SPDX licenses list and validation library.", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ - "license", - "spdx", - "validator" + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" ], - "time": "2018-04-30T10:33:04+00:00" + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" }, { - "name": "doctrine/collections", - "version": "v1.4.0", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" + "psr-4": { + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -304,68 +278,51 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "array", - "collections", - "iterator" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], - "time": "2017-01-03T10:49:41+00:00" + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.0.5", + "name": "psr/log", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -374,54 +331,53 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "constructor", - "instantiate" + "log", + "psr", + "psr-3" ], - "time": "2015-06-14T21:17:01+00:00" + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" }, { - "name": "gitonomy/gitlib", - "version": "v1.0.4", + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", "source": { "type": "git", - "url": "https://github.com/gitonomy/gitlib.git", - "reference": "932a960221ae3484a3e82553b3be478e56beb68d" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/932a960221ae3484a3e82553b3be478e56beb68d", - "reference": "932a960221ae3484a3e82553b3be478e56beb68d", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": "^5.3 || ^7.0", - "symfony/process": "^2.3|^3.0|^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.7", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Add some log" + "php": ">=8.1" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "3.6-dev" } }, "autoload": { - "psr-4": { - "Gitonomy\\Git\\": "src/Gitonomy/Git/" - } + "files": [ + "function.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -429,100 +385,88 @@ ], "authors": [ { - "name": "Alexandre Salomé", - "email": "alexandre.salome@gmail.com", - "homepage": "http://alexandre-salome.fr" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Julien DIDIER", - "email": "genzo.wm@gmail.com", - "homepage": "http://www.jdidier.net" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library for accessing git", - "homepage": "http://gitonomy.com", - "time": "2018-04-22T19:55:36+00:00" - }, - { - "name": "hamcrest/hamcrest-php", - "version": "v1.2.2", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpunit/php-file-iterator": "1.3.3", - "satooshi/php-coveralls": "dev-master" - }, - "type": "library", - "autoload": { - "classmap": [ - "hamcrest" - ], - "files": [ - "hamcrest/Hamcrest.php" - ] + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD" - ], - "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" + "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": "2015-05-11T14:41:42+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { - "name": "justinrainbow/json-schema", - "version": "5.2.7", + "name": "symfony/http-client", + "version": "v8.0.5", "source": { "type": "git", - "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23" + "url": "https://github.com/symfony/http-client.git", + "reference": "f9fdd372473e66469c6d32a4ed12efcffdea38c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23", + "url": "https://api.github.com/repos/symfony/http-client/zipball/f9fdd372473e66469c6d32a4ed12efcffdea38c4", + "reference": "f9fdd372473e66469c6d32a4ed12efcffdea38c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.4", + "psr/log": "^1|^2|^3", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "amphp/amp": "<3", + "php-http/discovery": "<1.15" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" + "amphp/http-client": "^5.3.2", + "amphp/http-tunnel": "^2.0", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/cache": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0" }, - "bin": [ - "bin/validate-json" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, "autoload": { "psr-4": { - "JsonSchema\\": "src/JsonSchema/" - } + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -530,152 +474,159 @@ ], "authors": [ { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v8.0.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" + "url": "https://github.com/fabpot", + "type": "github" }, { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "time": "2018-02-14T22:26:30+00:00" + "time": "2026-01-27T16:18:07+00:00" }, { - "name": "mockery/mockery", - "version": "0.9.9", + "name": "symfony/http-client-contracts", + "version": "v3.6.0", "source": { "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", - "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { - "hamcrest/hamcrest-php": "~1.1", - "lib-pcre": ">=7.0", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" + "php": ">=8.1" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "0.9.x-dev" + "dev-main": "3.6-dev" } }, "autoload": { - "psr-0": { - "Mockery": "library/" - } + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", - "homepage": "http://github.com/padraic/mockery", + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" - ], - "time": "2017-02-28T12:52:32+00:00" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.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": "2025-04-29T11:18:49+00:00" }, { - "name": "monolog/monolog", - "version": "1.23.0", + "name": "symfony/service-contracts", + "version": "v3.6.1", "source": { "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" - }, - "provide": { - "psr/log-implementation": "1.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", - "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "jakub-onderka/php-parallel-lint": "0.9", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpunit/phpunit": "~4.5", - "phpunit/phpunit-mock-objects": "2.3.0", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "^5.3|^6.0" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" + "conflict": { + "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { - "Monolog\\": "src/Monolog" - } + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -683,50 +634,84 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", "keywords": [ - "log", - "logging", - "psr-3" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ], - "time": "2017-06-19T01:22:40+00:00" - }, + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:30:57+00:00" + } + ], + "packages-dev": [ { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -740,38 +725,55 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" }, { - "name": "phar-io/manifest", - "version": "1.0.1", + "name": "nikic/php-parser", + "version": "v5.7.0", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^1.0.1", - "php": "^5.6 || ^7.0" + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -779,42 +781,48 @@ ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Nikita Popov" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" }, { - "name": "phar-io/version", - "version": "1.0.1", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -841,357 +849,163 @@ "role": "Developer" } ], - "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "url": "https://github.com/theseer", + "type": "github" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpro/grumphp", - "version": "v0.14.1", - "source": { - "type": "git", - "url": "https://github.com/phpro/grumphp.git", - "reference": "73288e15bfd7d5aba8e73a19a45f5eab411c3595" - }, + "name": "phpstan/phpstan", + "version": "1.12.32", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpro/grumphp/zipball/73288e15bfd7d5aba8e73a19a45f5eab411c3595", - "reference": "73288e15bfd7d5aba8e73a19a45f5eab411c3595", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", + "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", "shasum": "" }, "require": { - "composer-plugin-api": "~1.0", - "composer/composer": "^1.0", - "doctrine/collections": "~1.2", - "gitonomy/gitlib": "^1.0.3", - "monolog/monolog": "~1.16", - "php": ">=5.6.0", - "seld/jsonlint": "~1.1", - "symfony/config": "~2.7|~3.0|~4.0", - "symfony/console": "~2.7|~3.0|~4.0", - "symfony/dependency-injection": "~2.7|~3.0|~4.0", - "symfony/event-dispatcher": "~2.7|~3.0|~4.0", - "symfony/filesystem": "~2.7|~3.0|~4.0", - "symfony/finder": "~2.7|~3.0|~4.0", - "symfony/options-resolver": "~2.7|~3.0|~4.0", - "symfony/process": "~2.7|~3.0|~4.0", - "symfony/yaml": "~2.7|~3.0|~4.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~1|~2", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "nikic/php-parser": "~2.1", - "phpspec/phpspec": "^3.2.2", - "phpspec/prophecy": "^1.6.2", - "phpunit/phpunit": "^5.7.27|^6.4.4", - "sebastian/comparator": "^1.2.4", - "sensiolabs/security-checker": "^4.0", - "squizlabs/php_codesniffer": "~2.4" + "php": "^7.2|^8.0" }, - "suggest": { - "atoum/atoum": "Lets GrumPHP run your unit tests.", - "behat/behat": "Lets GrumPHP validate your project features.", - "codeception/codeception": "Lets GrumPHP run your project's full stack tests", - "codegyre/robo": "Lets GrumPHP run your automated PHP tasks.", - "doctrine/orm": "Lets GrumPHP validate your Doctrine mapping files.", - "etsy/phan": "Lets GrumPHP unleash a static analyzer on your code", - "friendsofphp/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.", - "infection/infection": "Lets GrumPHP evaluate the quality your unit tests", - "jakub-onderka/php-parallel-lint": "Lets GrumPHP quickly lint your entire code base.", - "maglnet/composer-require-checker": "Lets GrumPHP analyze composer dependencies.", - "malukenho/kawaii-gherkin": "Lets GrumPHP lint your Gherkin files.", - "nikic/php-parser": "Lets GrumPHP run static analyses through your PHP files.", - "phing/phing": "Lets GrumPHP run your automated PHP tasks.", - "phpmd/phpmd": "Lets GrumPHP sort out the mess in your code", - "phpspec/phpspec": "Lets GrumPHP spec your code.", - "phpstan/phpstan": "Lets GrumPHP discover bugs in your code without running it.", - "phpunit/phpunit": "Lets GrumPHP run your unit tests.", - "povils/phpmnd": "Lets GrumPHP help you detect magic numbers in PHP code.", - "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", - "sebastian/phpcpd": "Lets GrumPHP find duplicated code.", - "sensiolabs/security-checker": "Lets GrumPHP be sure that there are no known security issues.", - "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code.", - "sstalle/php7cc": "Lets GrumPHP check PHP 5.3 - 5.6 code compatibility with PHP 7." + "conflict": { + "phpstan/phpstan-shim": "*" }, "bin": [ - "bin/grumphp" + "phpstan", + "phpstan.phar" ], - "type": "composer-plugin", - "extra": { - "class": "GrumPHP\\Composer\\GrumPHPPlugin" - }, + "type": "library", "autoload": { - "psr-4": { - "GrumPHP\\": "src" - } + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Toon Verwerft", - "email": "toon.verwerft@phpro.be" - }, - { - "name": "Community", - "homepage": "https://github.com/phpro/grumphp/graphs/contributors" - } + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" ], - "description": "A composer plugin that enables source code quality checks.", - "time": "2018-05-25T12:19:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.7.6", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", - "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "url": "https://github.com/ondrejmirtes", + "type": "github" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "url": "https://github.com/phpstan", + "type": "github" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2018-04-18T13:57:24+00:00" + "time": "2025-09-30T10:16:31+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.3.2", + "version": "11.0.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": "^7.0", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "nikic/php-parser": "^5.7.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.1", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.3.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.5.46" }, "suggest": { - "ext-xdebug": "^2.5.5" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -1217,29 +1031,55 @@ "testing", "xunit" ], - "time": "2018-04-06T15:36:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-12-24T07:01:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1254,7 +1094,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1264,26 +1104,61 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" + } + ], + "time": "2026-02-02T13:52:54+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "5.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1300,37 +1175,48 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "template" + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { - "name": "phpunit/php-timer", - "version": "1.0.9", + "name": "phpunit/php-text-template", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1345,42 +1231,52 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "timer" + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "2.0.2", + "name": "phpunit/php-timer", + "version": "7.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1395,28 +1291,40 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "tokenizer" + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "6.5.9", + "version": "11.5.55", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f" + "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/093ca5508174cd8ab8efe44fd1dde447adfdec8f", - "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00", + "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00", "shasum": "" }, "require": { @@ -1425,35 +1333,31 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.0", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.3", - "phpunit/php-file-iterator": "^1.4.3", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^5.0.5", - "sebastian/comparator": "^2.1", - "sebastian/diff": "^2.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, - "require-dev": { - "ext-pdo": "*" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.12", + "phpunit/php-file-iterator": "^5.1.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.3", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.2", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/recursion-context": "^6.0.3", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -1461,10 +1365,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.5.x-dev" + "dev-main": "11.5-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -1487,41 +1394,59 @@ "testing", "xunit" ], - "time": "2018-07-03T06:40:40+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "5.0.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", - "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.0", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55" }, - "conflict": { - "phpunit/phpunit": "<6.0" + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2026-02-18T12:37:06+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, - "require-dev": { - "phpunit/phpunit": "^6.5" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" }, - "suggest": { - "ext-soap": "*" + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1540,134 +1465,165 @@ "role": "lead" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2018-05-29T13:50:43+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "sebastian/code-unit", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-02-14T16:28:37+00:00" + "time": "2025-03-19T07:56:08+00:00" }, { - "name": "psr/log", - "version": "1.0.2", + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "4.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "name": "sebastian/comparator", + "version": "6.3.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -1683,38 +1639,77 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-01-24T09:26:40+00:00" }, { - "name": "sebastian/comparator", - "version": "2.1.3", + "name": "sebastian/complexity", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", - "sebastian/exporter": "^3.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1727,56 +1722,52 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2018-02-01T13:46:46+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "2.0.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1789,46 +1780,63 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-08-03T08:09:46+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^11.3" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -1847,40 +1855,63 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -1893,6 +1924,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1901,54 +1936,73 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:12:51+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-uopz": "*" + "ext-dom": "*", + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1967,38 +2021,48 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.3", + "name": "sebastian/lines-of-code", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2013,37 +2077,51 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" }, { - "name": "sebastian/object-reflector", - "version": "1.1.1", + "name": "sebastian/object-enumerator", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -2061,34 +2139,45 @@ "email": "sebastian@phpunit.de" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" }, { - "name": "sebastian/recursion-context", - "version": "3.0.0", + "name": "sebastian/object-reflector", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2101,44 +2190,50 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { - "name": "sebastian/resource-operations", - "version": "1.0.0", + "name": "sebastian/recursion-context", + "version": "6.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -2154,964 +2249,237 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "seld/cli-prompt", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/cli-prompt.git", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Seld\\CliPrompt\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", - "keywords": [ - "cli", - "console", - "hidden", - "input", - "prompt" - ], - "time": "2017-03-18T11:32:45+00:00" - }, - { - "name": "seld/jsonlint", - "version": "1.7.1", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "time": "2018-01-24T12:46:19+00:00" - }, - { - "name": "seld/phar-utils", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/phar-utils.git", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Seld\\PharUtils\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "PHAR file format utilities, for when PHP phars you up", - "keywords": [ - "phra" - ], - "time": "2015-10-13T18:44:15+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.3.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d86873af43b4aa9d1f39a3601cc0cfcf02b25266" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d86873af43b4aa9d1f39a3601cc0cfcf02b25266", - "reference": "d86873af43b4aa9d1f39a3601cc0cfcf02b25266", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2018-06-06T23:58:19+00:00" - }, - { - "name": "symfony/config", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "1fffdeb349ff36a25184e5564c25289b1dbfc402" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/1fffdeb349ff36a25184e5564c25289b1dbfc402", - "reference": "1fffdeb349ff36a25184e5564c25289b1dbfc402", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3", - "symfony/finder": "<3.3" - }, - "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/event-dispatcher": "~3.3|~4.0", - "symfony/finder": "~3.3|~4.0", - "symfony/yaml": "~3.0|~4.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "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": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2018-06-19T14:02:58+00:00" - }, - { - "name": "symfony/console", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1b97071a26d028c9bd4588264e101e14f6e7cd00", - "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" - }, - "suggest": { - "psr/log-implementation": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "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": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2018-05-23T05:02:55+00:00" - }, - { - "name": "symfony/debug", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/47e6788c5b151cf0cfdf3329116bf33800632d75", - "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "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": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2018-06-25T11:10:40+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a0be80e3f8c11aca506e250c00bb100c04c35d10", - "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/container": "^1.0" - }, - "conflict": { - "symfony/config": "<3.3.7", - "symfony/finder": "<3.3", - "symfony/proxy-manager-bridge": "<3.4", - "symfony/yaml": "<3.4" - }, - "provide": { - "psr/container-implementation": "1.0" - }, - "require-dev": { - "symfony/config": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "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": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com", - "time": "2018-06-25T08:36:56+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fdd5abcebd1061ec647089c6c41a07ed60af09f8", - "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "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": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2018-04-06T07:35:25+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "8a721a5f2553c6c3482b1c5b22ed60fe94dd63ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/8a721a5f2553c6c3482b1c5b22ed60fe94dd63ed", - "reference": "8a721a5f2553c6c3482b1c5b22ed60fe94dd63ed", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "url": "https://github.com/sebastianbergmann", + "type": "github" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2018-06-21T11:10:19+00:00" - }, - { - "name": "symfony/finder", - "version": "v3.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", - "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2018-06-19T20:52:10+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { - "name": "symfony/options-resolver", - "version": "v3.4.12", + "name": "sebastian/type", + "version": "5.1.3", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "cc5e98ed91688a22a7162a8800096356f9076b1d" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc5e98ed91688a22a7162a8800096356f9076b1d", - "reference": "cc5e98ed91688a22a7162a8800096356f9076b1d", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "5.1-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony OptionsResolver Component", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "time": "2018-05-30T04:26:49+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/sebastianbergmann", + "type": "github" }, { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2018-04-30T19:57:29+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3296adf6a6454a050679cde90f95350ad604b171" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", - "reference": "3296adf6a6454a050679cde90f95350ad604b171", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { - "name": "symfony/process", - "version": "v3.4.12", + "name": "sebastian/version", + "version": "5.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "acc5a37c706ace827962851b69705b24e71ca17c" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/acc5a37c706ace827962851b69705b24e71ca17c", - "reference": "acc5a37c706ace827962851b69705b24e71ca17c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "5.0-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2018-05-30T04:24:30+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { - "name": "symfony/yaml", - "version": "v3.4.12", + "name": "staabm/side-effects-detector", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0" + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", - "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/staabm", + "type": "github" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-05-03T23:18:14+00:00" + "time": "2024-10-20T05:08:20+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -3131,57 +2499,17 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "url": "https://github.com/theseer", + "type": "github" } ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], @@ -3190,7 +2518,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "~7.0" + "php": "^8.5" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "2.2.0" } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..e31ab91 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 7 + paths: + - src + - tests \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..1fc2c3f --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,8 @@ + + + + + tests + + + \ No newline at end of file diff --git a/src/Client/Config.php b/src/Client/Config.php new file mode 100644 index 0000000..753dbb9 --- /dev/null +++ b/src/Client/Config.php @@ -0,0 +1,13 @@ +baseUrl, '/') . '/' . rawurlencode($ip); + } + + /** @param list $ips */ + public function bulk(array $ips): string + { + return rtrim($this->baseUrl, '/') . '/' . implode(',', array_map('rawurlencode', $ips)); + } + + public function requester(): string + { + return rtrim($this->baseUrl, '/') . '/check'; + } +} diff --git a/src/Client/IpstackClient.php b/src/Client/IpstackClient.php new file mode 100644 index 0000000..3d2ebba --- /dev/null +++ b/src/Client/IpstackClient.php @@ -0,0 +1,90 @@ +transport->get( + $this->endpoint->standard($ip), + $this->buildQuery($options) + ); + $this->throwIfApiError($data); + return $this->mapper->map($data); + } + + public function lookupRequester(?Options $options = null): IpstackResult + { + $data = $this->transport->get( + $this->endpoint->requester(), + $this->buildQuery($options) + ); + $this->throwIfApiError($data); + return $this->mapper->map($data); + } + + /** @param list $ips */ + public function lookupBulk(array $ips, ?Options $options = null): array + { + if (count($ips) === 0) return []; + if (count($ips) > 50) { + // ipstack documents bulk constraints and related errors; we enforce early. + throw new IpstackException('Bulk lookup supports up to 50 IPs per request.'); + } + + $data = $this->transport->get( + $this->endpoint->bulk($ips), + $this->buildQuery($options) + ); + $this->throwIfApiError($data); + + // bulk typically returns a list of results + if (!array_is_list($data)) { + // sometimes APIs return object; be defensive + return [$this->mapper->map($data)]; + } + + $out = []; + foreach ($data as $row) { + if (is_array($row)) { + $this->throwIfApiError($row); + $out[] = $this->mapper->map($row); + } + } + return $out; + } + + private function buildQuery(?Options $options): array + { + return array_merge( + ['access_key' => $this->config->accessKey], + $options?->toQuery() ?? [] + ); + } + + /** @param array $data */ + private function throwIfApiError(array $data): void + { + if (!isset($data['error']) || !is_array($data['error'])) return; + + $code = $data['error']['code'] ?? null; + $info = (string)($data['error']['info'] ?? 'Unknown API error'); + throw new ApiErrorException($code, $info); + } +} diff --git a/src/Client/Options.php b/src/Client/Options.php new file mode 100644 index 0000000..e8900f1 --- /dev/null +++ b/src/Client/Options.php @@ -0,0 +1,47 @@ + */ + private array $query = []; + + public static function create(): self + { + return new self(); + } + + /** @param list|string $fields */ + public function fields(array|string $fields): self + { + $this->query['fields'] = is_array($fields) ? implode(',', $fields) : $fields; + return $this; + } + + public function language(string $lang): self + { + $this->query['language'] = $lang; + return $this; + } + + public function security(bool $enabled = true): self + { + $this->query['security'] = $enabled ? 1 : 0; + return $this; + } + + public function hostname(bool $enabled = true): self + { + $this->query['hostname'] = $enabled ? 1 : 0; + return $this; + } + + /** @return array */ + public function toQuery(): array + { + return $this->query; + } +} diff --git a/src/Exception/ApiErrorException.php b/src/Exception/ApiErrorException.php new file mode 100644 index 0000000..ce44c7f --- /dev/null +++ b/src/Exception/ApiErrorException.php @@ -0,0 +1,15 @@ +accessKey = $key; + + return $this; + } + + public function withBaseUrl(string $baseUrl): self + { + $this->baseUrl = $baseUrl; + + return $this; + } + + public function withTransport(TransportInterface $transport): self + { + $this->transport = $transport; + + return $this; + } + + /** + * If you prefer PSR-18 wiring here, pass an adapter transport you create externally. + * (This factory stays PSR-only and dependency-light.) + */ + public function build(): IpstackClient + { + if ($this->accessKey === null || $this->accessKey === '') { + throw new \InvalidArgumentException('Access key is required.'); + } + + $config = new Config($this->accessKey, $this->baseUrl); + $endpoint = new Endpoint($this->baseUrl); + $mapper = new IpstackResultMapper(); + + if ($this->transport === null) { + throw new \InvalidArgumentException( + 'No transport configured. Provide a PSR-18 based transport via withTransport().' + ); + } + + return new IpstackClient($config, $endpoint, $this->transport, $mapper); + } +} diff --git a/src/Http/Request.php b/src/Http/Request.php deleted file mode 100644 index ff7c611..0000000 --- a/src/Http/Request.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ -class Request -{ - /** - * @var string - */ - protected $param = []; - - /** - * Create new instance. - * - * @param $param - */ - public function __construct($param) - { - $this->param = $param; - } - - /** - * @return mixed - */ - public function getEndPoint() - { - $url = sprintf('https://ipstack.com/ipstack_api.php?ip=%s', $this->param['ip']); - - if ($this->param['api_key']) { - $protocol = $this->param['secure'] ? 'https' : 'http'; - - $url = sprintf( - '%s://api.ipstack.com/%s?access_key=%s', - $protocol, - $this->param['ip'], - $this->param['api_key'] - ); - } - - return $url; - } - - /** - * @return \Sujip\Ipstack\Http\Response - */ - public function make() - { - if (empty($this->param['ip'])) { - $this->throwException('Error: No IP specified', 403); - } - - try { - $response = file_get_contents($this->getEndPoint()); - } catch (Exception $e) { - $this->throwException('Forbidden', 403); - } - - return new Response($response); - } - - /** - * @param $message - * @param $code - * - * @return \Sujip\Ipstack\Exception\Forbidden - */ - public function throwException($message, $code = 400) - { - throw new Forbidden($message, $code); - } -} diff --git a/src/Http/Response.php b/src/Http/Response.php deleted file mode 100644 index 130605a..0000000 --- a/src/Http/Response.php +++ /dev/null @@ -1,30 +0,0 @@ -response = $response; - } - - /** - * @return mixed - */ - public function getBody() - { - return json_decode($this->response, true); - } -} diff --git a/src/Ipstack.php b/src/Ipstack.php index 64c65ee..8ece543 100644 --- a/src/Ipstack.php +++ b/src/Ipstack.php @@ -1,275 +1,15 @@ ip = $ip; - $this->api_key = $api_key; - } - - /** - * Set HTTPS mode on for API call. - * - * @return boolean - */ - public function secure() - { - $this->secure = true; - - return $this; - } - - /** - * Make an API call with IP - * - * @return \Sujip\Ipstack\Http\Response - */ - public function call() - { - try { - $request = new Request([ - 'ip' => $this->ip, - 'api_key' => $this->api_key, - 'secure' => $this->secure, - ]); - - $response = $request->make(); - } catch (Forbidden $e) { - throw new Forbidden('Error: No IP specified', 403); - } - - return $response->getBody(); - } - - /** - * Resolve if the API returns the coulumn. - * - * @param $key - * @param $default - */ - public function resolve($key, $default = null) - { - if (!sizeof($this->items)) { - $this->items = $this->call(); - } +use Ipstack\Factory\IpstackFactory; - if (isset($this->items[$key])) { - return $this->items[$key]; - } - - return $default; - } - - /** - * Get formatted address by IP - * eg: Kathmandu, Central Region, Nepal - * - * @return string - */ - public function formatted() - { - $address = array_filter([ - $this->city(), - $this->zip(), - $this->region(), - $this->country(), - ]); - - return implode(', ', $address); - } - - /** - * Get IP address, eg: 27.34.19.106 - * - * @return string - */ - public function ip() - { - return $this->resolve('ip'); - } - - /** - * Get continent eg: Asia - * - * @return string - */ - public function continent() - { - return $this->resolve('continent_name'); - } - - /** - * Get continent_code eg AS - * - * @return string - */ - public function continentCode() - { - return $this->resolve('continent_code'); - } - - /** - * Get country code, eg:NP - * - * @return string - */ - public function countryCode() - { - return $this->resolve('country_code'); - } - - /** - * Get country name, eg: Nepal - * - * @return string - */ - public function country() - { - return $this->resolve('country_name'); - } - - /** - * Get your region eg: Central Region - * - * @return string - */ - public function region() - { - return $this->resolve('region_name'); - } - - /** - * Gey your region_code: 1 - * - * @return string - */ - public function regionCode() - { - return $this->resolve('region_code'); - } - - /** - * Get city, eg: Kathmandu - * - * @return string - */ - public function city() - { - return $this->resolve('city'); - } - - /** - * Get zip code, eg: 33700 - * - * @return string - */ - public function zip() - { - return $this->resolve('zip'); - } - - /** - * Get your capital eg: Kathmandu - * - * @return string - */ - public function capital() - { - return $this->resolve('location')['capital'] ?? null; - } - - /** - * Get latitude eg: 27.6667 - * - * @return string - */ - public function latitude() - { - return $this->resolve('latitude'); - } - - /** - * Get longitude eg: 85.3167 - * - * @return string - */ - public function longitude() - { - return $this->resolve('longitude'); - } - - /** - * Get timezone eg: Asia/Kathmandu - * - * @return string - */ - public function timezone() - { - return $this->resolve('time_zone')['id'] ?? null; - } - - /** - * Get connection, isp eg: WorldLink Communications Pvt Ltd - * - * @return string - */ - public function isp() - { - return $this->resolve('connection')['isp'] ?? null; - } - - /** - * Get curreny code eg: NPR - * - * @return string - */ - public function currency() - { - return $this->resolve('currency')['code'] ?? null; - } - - /** - * Get the currency name eg: Nepalese Rupee - * - * @return string - */ - public function currencyName() +final class Ipstack +{ + public static function factory(): IpstackFactory { - return $this->resolve('currency')['name'] ?? null; + return new IpstackFactory(); } } diff --git a/src/Mapper/IpstackResultMapper.php b/src/Mapper/IpstackResultMapper.php new file mode 100644 index 0000000..96ee762 --- /dev/null +++ b/src/Mapper/IpstackResultMapper.php @@ -0,0 +1,117 @@ + $data */ + public function map(array $data): IpstackResult + { + $country = $this->hydrate(Country::class, $data); + $region = $this->hydrate(Region::class, $data); + + $location = null; + if (isset($data['location']) && is_array($data['location'])) { + $location = new Location( + capital: $data['location']['capital'] ?? null, + languages: is_array($data['location']['languages'] ?? null) ? $data['location']['languages'] : [], + ); + } + + $connection = null; + if (isset($data['connection']) && is_array($data['connection'])) { + $c = $data['connection']; + $connection = new Connection( + asn: isset($c['asn']) ? (int)$c['asn'] : null, + isp: $c['isp'] ?? null, + sld: $c['sld'] ?? null, + tld: $c['tld'] ?? null, + carrier: $c['carrier'] ?? null, + home: isset($c['home']) ? (bool)$c['home'] : null, + organizationType: $c['organization_type'] ?? null, + isicCode: $c['isic_code'] ?? null, + naicsCode: $c['naics_code'] ?? null, + ); + } + + $security = null; + if (isset($data['security']) && is_array($data['security'])) { + $s = $data['security']; + $security = new Security( + isProxy: isset($s['is_proxy']) ? (bool)$s['is_proxy'] : null, + isVpn: isset($s['is_vpn']) ? (bool)$s['is_vpn'] : null, + isTor: isset($s['is_tor']) ? (bool)$s['is_tor'] : null, + proxyLastDetected: $s['proxy_last_detected'] ?? null, + proxyLevel: $s['proxy_level'] ?? null, + vpnService: $s['vpn_service'] ?? null, + anonymizerStatus: $s['anonymizer_status'] ?? null, + hostingFacility: $s['hosting_facility'] ?? null, + ); + } + + // Routing fields are top-level in the response (per changelog additions) + $routing = new Routing( + msa: $data['msa'] ?? null, + dma: $data['dma'] ?? null, + radius: isset($data['radius']) ? (float)$data['radius'] : null, + ipRoutingTyp: $data['ip_routing_typ'] ?? null, + connectionType: $data['connection_type'] ?? null, + ); + + return new IpstackResult( + ip: (string)($data['ip'] ?? ''), + type: $data['type'] ?? null, + city: $data['city'] ?? null, + zip: $data['zip'] ?? null, + latitude: isset($data['latitude']) ? (float)$data['latitude'] : null, + longitude: isset($data['longitude']) ? (float)$data['longitude'] : null, + + country: $country, + region: $region, + location: $location, + connection: $connection, + security: $security, + routing: $routing, + + raw: $data + ); + } + + /** @param array $data */ + private function hydrate(string $class, array $data): object + { + $rc = new ReflectionClass($class); + $args = []; + + foreach ($rc->getConstructor()?->getParameters() ?? [] as $p) { + $name = $p->getName(); + $prop = $rc->hasProperty($name) ? $rc->getProperty($name) : null; + + $key = $name; + if ($prop) { + $attrs = $prop->getAttributes(MapFrom::class); + if ($attrs) { + $key = $attrs[0]->newInstance()->key; + } + } + + $args[$name] = $data[$key] ?? $p->getDefaultValue(); + } + + return $rc->newInstanceArgs($args); + } +} diff --git a/src/Model/Attributes/MapFrom.php b/src/Model/Attributes/MapFrom.php new file mode 100644 index 0000000..52eca67 --- /dev/null +++ b/src/Model/Attributes/MapFrom.php @@ -0,0 +1,11 @@ + */ + private readonly array $raw = [], + ) {} + + public function formatted(): string + { + $parts = array_filter([$this->city, $this->zip, $this->region->name, $this->country->name]); + return implode(', ', $parts); + } + + /** @return array */ + public function raw(): array + { + return $this->raw; + } + + public function jsonSerialize(): array + { + return $this->raw; + } +} diff --git a/src/Model/Location.php b/src/Model/Location.php new file mode 100644 index 0000000..536ea92 --- /dev/null +++ b/src/Model/Location.php @@ -0,0 +1,16 @@ + $languages + */ + public function __construct( + public readonly ?string $capital = null, + public readonly array $languages = [], + ) {} +} diff --git a/src/Model/Region.php b/src/Model/Region.php new file mode 100644 index 0000000..bcbc501 --- /dev/null +++ b/src/Model/Region.php @@ -0,0 +1,15 @@ +requests->createRequest('GET', $full); + + try { + $res = $this->http->sendRequest($req); + } catch (\Throwable $e) { + throw new TransportException('HTTP request failed: ' . $e->getMessage(), 0, $e); + } + + $code = $res->getStatusCode(); + if ($code < 200 || $code >= 300) { + throw new TransportException("Unexpected HTTP status: {$code}"); + } + + $body = (string)$res->getBody(); + $data = json_decode($body, true); + + if (!is_array($data)) { + throw new InvalidResponseException('Invalid JSON response'); + } + return $data; + } +} diff --git a/src/Transport/TransportInterface.php b/src/Transport/TransportInterface.php new file mode 100644 index 0000000..4ac52e5 --- /dev/null +++ b/src/Transport/TransportInterface.php @@ -0,0 +1,11 @@ + */ + public function get(string $url, array $query): array; +} diff --git a/tests/Fakes/FakeTransport.php b/tests/Fakes/FakeTransport.php new file mode 100644 index 0000000..88f8b05 --- /dev/null +++ b/tests/Fakes/FakeTransport.php @@ -0,0 +1,24 @@ + */ + private array $next; + + /** @param array $next */ + public function __construct(array $next) + { + $this->next = $next; + } + + public function get(string $url, array $query): array + { + return $this->next; + } +} diff --git a/tests/IpstackClientTest.php b/tests/IpstackClientTest.php new file mode 100644 index 0000000..f50e75a --- /dev/null +++ b/tests/IpstackClientTest.php @@ -0,0 +1,72 @@ + '8.8.8.8', + 'country_name' => 'United States', + 'country_code' => 'US', + 'region_name' => 'California', + 'region_code' => 'CA', + 'city' => 'Mountain View', + 'zip' => '94035', + 'security' => [ + 'is_proxy' => false, + 'proxy_level' => 'none' + ], + 'connection' => [ + 'asn' => 15169, + 'isp' => 'Google LLC', + 'tld' => 'com' + ], + 'msa' => 'San Francisco-Oakland-Berkeley' + ]); + + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + $fake, + new IpstackResultMapper() + ); + + $result = $client->lookup('8.8.8.8', Options::create()->security()); + + $this->assertSame('United States', $result->country->name); + $this->assertSame('California', $result->region->name); + $this->assertSame('Mountain View, 94035, California, United States', $result->formatted()); + $this->assertSame(15169, $result->connection?->asn); + $this->assertSame('none', $result->security?->proxyLevel); + } + + public function testApiErrorThrows(): void + { + $fake = new FakeTransport([ + 'error' => ['code' => 101, 'info' => 'Invalid access key'] + ]); + + $client = new IpstackClient( + new Config('BAD'), + new Endpoint('https://api.ipstack.com'), + $fake, + new IpstackResultMapper() + ); + + $this->expectException(ApiErrorException::class); + $client->lookup('8.8.8.8'); + } +} diff --git a/tests/IpstackTest.php b/tests/IpstackTest.php deleted file mode 100644 index c29ec43..0000000 --- a/tests/IpstackTest.php +++ /dev/null @@ -1,49 +0,0 @@ -payload = file_get_contents(__DIR__ . '/Mock/Response/response.json'); - } - - public function tearDown() - { - $this->payload = null; - } - - public function testShouldThrowExceptionForEmptyIpHost() - { - $this->expectException(Forbidden::class); - $this->expectExceptionMessage('Error: No IP specified'); - $this->expectExceptionCode(403); - - $geo = (new Ipstack(''))->call(); - } - - public function testShouldReturnValidResponse() - { - $body = $this->payload; - - $result = (new Response($body))->getBody(); - - $body = json_decode($body, true); - - $this->assertEquals($body, $result); - } -} diff --git a/tests/Mock/Response/response.json b/tests/Mock/Response/response.json deleted file mode 100644 index 05dcc45..0000000 --- a/tests/Mock/Response/response.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "ip":"27.34.19.106", - "hostname":"27.34.19.106", - "type":"ipv4", - "continent_code":"AS", - "continent_name":"Asia", - "country_code":"NP", - "country_name":"Nepal", - "region_code":"1", - "region_name":"Central Region", - "city":"Jawalakhel", - "zip":null, - "latitude":27.6667, - "longitude":85.3167, - "location":{ - "geoname_id":1283312, - "capital":"Kathmandu", - "languages":[ - { - "code":"ne", - "name":"Nepali", - "native":"\u0928\u0947\u092a\u093e\u0932\u0940" - } - ], - "country_flag":"http:\/\/assets.ipstack.com\/flags\/np.svg", - "country_flag_emoji":"\ud83c\uddf3\ud83c\uddf5", - "country_flag_emoji_unicode":"U+1F1F3 U+1F1F5", - "calling_code":"977", - "is_eu":false - }, - "time_zone":{ - "id":"Asia\/Kathmandu", - "current_time":"2018-07-06T14:16:47+05:45", - "gmt_offset":20700, - "code":"+0545", - "is_daylight_saving":false - }, - "currency":{ - "code":"NPR", - "name":"Nepalese Rupee", - "plural":"Nepalese rupees", - "symbol":"NPRs", - "symbol_native":"\u0928\u0947\u0930\u0942" - }, - "connection":{ - "asn":17501, - "isp":"WorldLink Communications Pvt Ltd" - }, - "security":{ - "is_proxy":false, - "proxy_type":null, - "is_crawler":false, - "crawler_name":null, - "crawler_type":null, - "is_tor":false, - "threat_level":"low", - "threat_types":null - } -} From 72c3e29caa9687ce8b2120ecda0db451eccb80f7 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 16:18:12 +0545 Subject: [PATCH 03/11] Fixed phpstan, tests --- .github/workflows/ci.yml | 42 ++++++++++++-- .phpunit.cache/test-results | 2 +- src/Client/Config.php | 1 + src/Client/IpstackClient.php | 59 +++++++++++++++----- src/Exception/ApiErrorException.php | 2 +- src/Exception/BatchNotSupportedException.php | 7 +++ src/Exception/InvalidFieldsException.php | 7 +++ src/Exception/RateLimitException.php | 7 +++ src/Exception/TooManyIpsException.php | 7 +++ src/Factory/IpstackFactory.php | 13 +++++ src/Mapper/IpstackResultMapper.php | 12 +++- src/Model/IpstackCollection.php | 35 ++++++++++++ src/Model/IpstackResult.php | 4 ++ src/Transport/Psr18Transport.php | 6 ++ src/Transport/TransportInterface.php | 5 +- tests/Fakes/FakeTransport.php | 4 ++ tests/IpstackClientTest.php | 18 ++++++ 17 files changed, 209 insertions(+), 22 deletions(-) create mode 100644 src/Exception/BatchNotSupportedException.php create mode 100644 src/Exception/InvalidFieldsException.php create mode 100644 src/Exception/RateLimitException.php create mode 100644 src/Exception/TooManyIpsException.php create mode 100644 src/Model/IpstackCollection.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b8d4ae..1ada974 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,27 +2,61 @@ name: CI on: push: + branches: ["main", "master"] pull_request: +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + jobs: test: runs-on: ubuntu-latest + strategy: + fail-fast: false matrix: - php: ['8.5'] + php: ['8.3', '8.4', '8.5'] + dependency-version: ['prefer-stable', 'prefer-lowest'] + steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} coverage: none + tools: composer:v2 + extensions: mbstring, json + + - name: Validate composer.json + run: composer validate --strict + + - name: Get Composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ matrix.dependency-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.php }}- - name: Install dependencies - run: composer install --no-interaction --prefer-dist + run: | + composer update --${{ matrix.dependency-version }} \ + --no-interaction \ + --prefer-dist \ + --no-progress - - name: Run tests + - name: Run PHPUnit run: composer test - name: Run PHPStan diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results index 55b4b08..53f682f 100644 --- a/.phpunit.cache/test-results +++ b/.phpunit.cache/test-results @@ -1 +1 @@ -{"version":2,"defects":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":8},"times":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":0.004,"Ipstack\\Tests\\IpstackClientTest::testApiErrorThrows":0.001}} \ No newline at end of file +{"version":2,"defects":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":8},"times":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":0.007,"Ipstack\\Tests\\IpstackClientTest::testApiErrorThrows":0.001,"Ipstack\\Tests\\IpstackClientTest::testRateLimitMapsToTypedException":0}} \ No newline at end of file diff --git a/src/Client/Config.php b/src/Client/Config.php index 753dbb9..bef700d 100644 --- a/src/Client/Config.php +++ b/src/Client/Config.php @@ -7,6 +7,7 @@ final class Config { public function __construct( + #[\SensitiveParameter] public readonly string $accessKey, public readonly string $baseUrl = 'https://api.ipstack.com' ) {} diff --git a/src/Client/IpstackClient.php b/src/Client/IpstackClient.php index 3d2ebba..77dc15d 100644 --- a/src/Client/IpstackClient.php +++ b/src/Client/IpstackClient.php @@ -5,8 +5,13 @@ namespace Ipstack\Client; use Ipstack\Exception\ApiErrorException; +use Ipstack\Exception\BatchNotSupportedException; +use Ipstack\Exception\InvalidFieldsException; use Ipstack\Exception\IpstackException; +use Ipstack\Exception\RateLimitException; +use Ipstack\Exception\TooManyIpsException; use Ipstack\Mapper\IpstackResultMapper; +use Ipstack\Model\IpstackCollection; use Ipstack\Model\IpstackResult; use Ipstack\Transport\TransportInterface; @@ -39,37 +44,52 @@ public function lookupRequester(?Options $options = null): IpstackResult return $this->mapper->map($data); } - /** @param list $ips */ - public function lookupBulk(array $ips, ?Options $options = null): array + /** + * @param list $ips + */ + public function lookupBulk(array $ips, ?Options $options = null): IpstackCollection { - if (count($ips) === 0) return []; + if ($ips === []) { + return new IpstackCollection([]); + } + if (count($ips) > 50) { - // ipstack documents bulk constraints and related errors; we enforce early. throw new IpstackException('Bulk lookup supports up to 50 IPs per request.'); } + /** @var array $data */ $data = $this->transport->get( $this->endpoint->bulk($ips), $this->buildQuery($options) ); - $this->throwIfApiError($data); - // bulk typically returns a list of results + // If API error wrapper returned (assoc), throw if (!array_is_list($data)) { - // sometimes APIs return object; be defensive - return [$this->mapper->map($data)]; + /** @var array $assoc */ + $assoc = $data; + $this->throwIfApiError($assoc); + return new IpstackCollection([$this->mapper->map($assoc)]); } $out = []; foreach ($data as $row) { - if (is_array($row)) { - $this->throwIfApiError($row); - $out[] = $this->mapper->map($row); + if (!is_array($row)) { + continue; } + + /** @var array $rowAssoc */ + $rowAssoc = $row; + + $this->throwIfApiError($rowAssoc); + $out[] = $this->mapper->map($rowAssoc); } - return $out; + + return new IpstackCollection($out); } + /** + * @return array + */ private function buildQuery(?Options $options): array { return array_merge( @@ -85,6 +105,19 @@ private function throwIfApiError(array $data): void $code = $data['error']['code'] ?? null; $info = (string)($data['error']['info'] ?? 'Unknown API error'); - throw new ApiErrorException($code, $info); + + // Map known ipstack error codes to domain exceptions + switch ((int)$code) { + case 104: + throw new RateLimitException($code, $info); + case 301: + throw new InvalidFieldsException($code, $info); + case 302: + throw new TooManyIpsException($code, $info); + case 303: + throw new BatchNotSupportedException($code, $info); + default: + throw new ApiErrorException($code, $info); + } } } diff --git a/src/Exception/ApiErrorException.php b/src/Exception/ApiErrorException.php index ce44c7f..b73d3bd 100644 --- a/src/Exception/ApiErrorException.php +++ b/src/Exception/ApiErrorException.php @@ -4,7 +4,7 @@ namespace Ipstack\Exception; -final class ApiErrorException extends IpstackException +class ApiErrorException extends IpstackException { public function __construct( public readonly int|string|null $apiCode, diff --git a/src/Exception/BatchNotSupportedException.php b/src/Exception/BatchNotSupportedException.php new file mode 100644 index 0000000..1eeeeb2 --- /dev/null +++ b/src/Exception/BatchNotSupportedException.php @@ -0,0 +1,7 @@ +transport = new Psr18Transport($client, $requestFactory); + + return $this; + } + /** * If you prefer PSR-18 wiring here, pass an adapter transport you create externally. * (This factory stays PSR-only and dependency-light.) diff --git a/src/Mapper/IpstackResultMapper.php b/src/Mapper/IpstackResultMapper.php index 96ee762..13c6d6d 100644 --- a/src/Mapper/IpstackResultMapper.php +++ b/src/Mapper/IpstackResultMapper.php @@ -21,8 +21,11 @@ final class IpstackResultMapper /** @param array $data */ public function map(array $data): IpstackResult { + /** @var Country $country */ $country = $this->hydrate(Country::class, $data); - $region = $this->hydrate(Region::class, $data); + + /** @var Region $region */ + $region = $this->hydrate(Region::class, $data); $location = null; if (isset($data['location']) && is_array($data['location'])) { @@ -91,7 +94,12 @@ public function map(array $data): IpstackResult ); } - /** @param array $data */ + /** + * @template T of object + * @param class-string $class + * @param array $data + * @return T + */ private function hydrate(string $class, array $data): object { $rc = new ReflectionClass($class); diff --git a/src/Model/IpstackCollection.php b/src/Model/IpstackCollection.php new file mode 100644 index 0000000..75166ca --- /dev/null +++ b/src/Model/IpstackCollection.php @@ -0,0 +1,35 @@ + */ +final class IpstackCollection implements IteratorAggregate, Countable +{ + /** @param list $items */ + public function __construct(private readonly array $items) {} + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->items); + } + + public function count(): int + { + return count($this->items); + } + + /** @return list */ + public function all(): array + { + return $this->items; + } +} diff --git a/src/Model/IpstackResult.php b/src/Model/IpstackResult.php index 3a9cff4..9df8997 100644 --- a/src/Model/IpstackResult.php +++ b/src/Model/IpstackResult.php @@ -31,6 +31,7 @@ public function __construct( public function formatted(): string { $parts = array_filter([$this->city, $this->zip, $this->region->name, $this->country->name]); + return implode(', ', $parts); } @@ -40,6 +41,9 @@ public function raw(): array return $this->raw; } + /** + * @return array + */ public function jsonSerialize(): array { return $this->raw; diff --git a/src/Transport/Psr18Transport.php b/src/Transport/Psr18Transport.php index cb194b9..71ee49c 100644 --- a/src/Transport/Psr18Transport.php +++ b/src/Transport/Psr18Transport.php @@ -16,6 +16,10 @@ public function __construct( private readonly RequestFactoryInterface $requests ) {} + /** + * @param array $query + * @return array + */ public function get(string $url, array $query): array { $full = $url . (str_contains($url, '?') ? '&' : '?') . http_build_query($query); @@ -28,6 +32,7 @@ public function get(string $url, array $query): array } $code = $res->getStatusCode(); + if ($code < 200 || $code >= 300) { throw new TransportException("Unexpected HTTP status: {$code}"); } @@ -38,6 +43,7 @@ public function get(string $url, array $query): array if (!is_array($data)) { throw new InvalidResponseException('Invalid JSON response'); } + return $data; } } diff --git a/src/Transport/TransportInterface.php b/src/Transport/TransportInterface.php index 4ac52e5..ad55626 100644 --- a/src/Transport/TransportInterface.php +++ b/src/Transport/TransportInterface.php @@ -6,6 +6,9 @@ interface TransportInterface { - /** @return array */ + /** + * @param array $query + * @return array + */ public function get(string $url, array $query): array; } diff --git a/tests/Fakes/FakeTransport.php b/tests/Fakes/FakeTransport.php index 88f8b05..048e31d 100644 --- a/tests/Fakes/FakeTransport.php +++ b/tests/Fakes/FakeTransport.php @@ -17,6 +17,10 @@ public function __construct(array $next) $this->next = $next; } + /** + * @param array $query + * @return array + */ public function get(string $url, array $query): array { return $this->next; diff --git a/tests/IpstackClientTest.php b/tests/IpstackClientTest.php index f50e75a..9253ee2 100644 --- a/tests/IpstackClientTest.php +++ b/tests/IpstackClientTest.php @@ -12,6 +12,7 @@ use Ipstack\Mapper\IpstackResultMapper; use Ipstack\Tests\Fakes\FakeTransport; use PHPUnit\Framework\TestCase; +use Ipstack\Exception\RateLimitException; final class IpstackClientTest extends TestCase { @@ -69,4 +70,21 @@ public function testApiErrorThrows(): void $this->expectException(ApiErrorException::class); $client->lookup('8.8.8.8'); } + + public function testRateLimitMapsToTypedException(): void + { + $fake = new FakeTransport([ + 'error' => ['code' => 104, 'info' => 'Usage limit reached'] + ]); + + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + $fake, + new IpstackResultMapper() + ); + + $this->expectException(RateLimitException::class); + $client->lookup('8.8.8.8'); + } } From 98adc3516f6f5163f435fe14c57de5b68b7ce735 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 16:27:51 +0545 Subject: [PATCH 04/11] CI updated --- .github/workflows/ci.yml | 2 +- composer.lock | 2525 -------------------------------------- grumphp.yml | 15 - 3 files changed, 1 insertion(+), 2541 deletions(-) delete mode 100755 composer.lock delete mode 100644 grumphp.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ada974..5d1612e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.3', '8.4', '8.5'] + php: ['8.5'] dependency-version: ['prefer-stable', 'prefer-lowest'] steps: diff --git a/composer.lock b/composer.lock deleted file mode 100755 index f4731e2..0000000 --- a/composer.lock +++ /dev/null @@ -1,2525 +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": "839833b42a617ccf1654a6ed7efc216b", - "packages": [ - { - "name": "nyholm/psr7", - "version": "1.8.2", - "source": { - "type": "git", - "url": "https://github.com/Nyholm/psr7.git", - "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", - "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", - "shasum": "" - }, - "require": { - "php": ">=7.2", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0" - }, - "provide": { - "php-http/message-factory-implementation": "1.0", - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "http-interop/http-factory-tests": "^0.9", - "php-http/message-factory": "^1.0", - "php-http/psr7-integration-tests": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", - "symfony/error-handler": "^4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Nyholm\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com" - }, - { - "name": "Martijn van der Ven", - "email": "martijn@vanderven.se" - } - ], - "description": "A fast PHP7 implementation of PSR-7", - "homepage": "https://tnyholm.se", - "keywords": [ - "psr-17", - "psr-7" - ], - "support": { - "issues": "https://github.com/Nyholm/psr7/issues", - "source": "https://github.com/Nyholm/psr7/tree/1.8.2" - }, - "funding": [ - { - "url": "https://github.com/Zegnat", - "type": "github" - }, - { - "url": "https://github.com/nyholm", - "type": "github" - } - ], - "time": "2024-09-09T07:06:30+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/http-client", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client" - }, - "time": "2023-09-23T14:17:50+00:00" - }, - { - "name": "psr/http-factory", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, - "time": "2024-04-15T12:06:14+00:00" - }, - { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.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/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "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.6.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": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/http-client", - "version": "v8.0.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "f9fdd372473e66469c6d32a4ed12efcffdea38c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/f9fdd372473e66469c6d32a4ed12efcffdea38c4", - "reference": "f9fdd372473e66469c6d32a4ed12efcffdea38c4", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "psr/log": "^1|^2|^3", - "symfony/http-client-contracts": "~3.4.4|^3.5.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "amphp/amp": "<3", - "php-http/discovery": "<1.15" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/http-client": "^5.3.2", - "amphp/http-tunnel": "^2.0", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/cache": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/messenger": "^7.4|^8.0", - "symfony/process": "^7.4|^8.0", - "symfony/rate-limiter": "^7.4|^8.0", - "symfony/stopwatch": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "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 powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v8.0.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-27T16:18:07+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "75d7043853a42837e68111812f4d964b01e5101c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", - "reference": "75d7043853a42837e68111812f4d964b01e5101c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "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 HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.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": "2025-04-29T11:18:49+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.6.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "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.6.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - } - ], - "packages-dev": [ - { - "name": "myclabs/deep-copy", - "version": "1.13.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-08-01T08:46:24+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.7.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.12.32", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", - "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2025-09-30T10:16:31+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "11.0.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", - "php": ">=8.2", - "phpunit/php-file-iterator": "^5.1.0", - "phpunit/php-text-template": "^4.0.1", - "sebastian/code-unit-reverse-lookup": "^4.0.1", - "sebastian/complexity": "^4.0.1", - "sebastian/environment": "^7.2.1", - "sebastian/lines-of-code": "^3.0.1", - "sebastian/version": "^5.0.2", - "theseer/tokenizer": "^1.3.1" - }, - "require-dev": { - "phpunit/phpunit": "^11.5.46" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "11.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", - "type": "tidelift" - } - ], - "time": "2025-12-24T07:01:01+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", - "type": "tidelift" - } - ], - "time": "2026-02-02T13:52:54+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^11.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:07:44+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:08:43+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "7.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:09:35+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "11.5.55", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00", - "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.12", - "phpunit/php-file-iterator": "^5.1.1", - "phpunit/php-invoker": "^5.0.1", - "phpunit/php-text-template": "^4.0.1", - "phpunit/php-timer": "^7.0.1", - "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.3", - "sebastian/comparator": "^6.3.3", - "sebastian/diff": "^6.0.2", - "sebastian/environment": "^7.2.1", - "sebastian/exporter": "^6.3.2", - "sebastian/global-state": "^7.0.2", - "sebastian/object-enumerator": "^6.0.1", - "sebastian/recursion-context": "^6.0.3", - "sebastian/type": "^5.1.3", - "sebastian/version": "^5.0.2", - "staabm/side-effects-detector": "^1.0.5" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "11.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2026-02-18T12:37:06+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:41:36+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-03-19T07:56:08+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:45:54+00:00" - }, - { - "name": "sebastian/comparator", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/diff": "^6.0", - "sebastian/exporter": "^6.0" - }, - "require-dev": { - "phpunit/phpunit": "^11.4" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2026-01-24T09:26:40+00:00" - }, - { - "name": "sebastian/complexity", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:49:50+00:00" - }, - { - "name": "sebastian/diff", - "version": "6.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "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" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:53:05+00:00" - }, - { - "name": "sebastian/environment", - "version": "7.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", - "type": "tidelift" - } - ], - "time": "2025-05-21T11:55:47+00:00" - }, - { - "name": "sebastian/exporter", - "version": "6.3.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/recursion-context": "^6.0" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" - } - ], - "time": "2025-09-24T06:12:51+00:00" - }, - { - "name": "sebastian/global-state", - "version": "7.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:57:36+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:58:38+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "6.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:00:13+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:01:32+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "6.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" - } - ], - "time": "2025-08-13T04:42:22+00:00" - }, - { - "name": "sebastian/type", - "version": "5.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" - } - ], - "time": "2025-08-09T06:55:48+00:00" - }, - { - "name": "sebastian/version", - "version": "5.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-10-09T05:16:32+00:00" - }, - { - "name": "staabm/side-effects-detector", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" - ], - "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" - }, - "funding": [ - { - "url": "https://github.com/staabm", - "type": "github" - } - ], - "time": "2024-10-20T05:08:20+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2025-11-17T20:03:58+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": "^8.5" - }, - "platform-dev": [], - "plugin-api-version": "2.2.0" -} diff --git a/grumphp.yml b/grumphp.yml deleted file mode 100644 index bf81fa5..0000000 --- a/grumphp.yml +++ /dev/null @@ -1,15 +0,0 @@ -parameters: - git_dir: . - bin_dir: vendor/bin - tasks: - phpunit: - config_file: ~ - testsuite: ~ - group: [] - always_execute: false - phpcs: - standard: PSR2 - warning_severity: ~ - ignore_patterns: - - tests/ - triggered_by: [php] From 340304c55c1cbad66cc718eb3f2ff55949e61c76 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 16:29:58 +0545 Subject: [PATCH 05/11] .gitignore --- .phpunit.cache/test-results | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .phpunit.cache/test-results diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index 53f682f..0000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":8},"times":{"Ipstack\\Tests\\IpstackClientTest::testLookupMapsModels":0.007,"Ipstack\\Tests\\IpstackClientTest::testApiErrorThrows":0.001,"Ipstack\\Tests\\IpstackClientTest::testRateLimitMapsToTypedException":0}} \ No newline at end of file From 6c45a0193fb938641ef6808902e8c0f3741f1cf4 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 16:46:42 +0545 Subject: [PATCH 06/11] docs: modernize README and add v1-to-v2 migration guide --- README.md | 311 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 269 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 64d14f0..e612095 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,314 @@ -## A Simple Package for IP to Location implementation with PHP using real-time API service through https://ipstack.com. +# ipstack PHP Client -[![Build Status](https://travis-ci.com/sudiptpa/ipstack.svg?branch=master)](https://travis-ci.com/sudiptpa/ipstack) -[![Latest Stable Version](https://poser.pugx.org/sudiptpa/ipstack/v/stable)](https://packagist.org/packages/sudiptpa/ipstack) -[![Total Downloads](https://poser.pugx.org/sudiptpa/ipstack/downloads)](https://packagist.org/packages/sudiptpa/ipstack) -[![License](https://poser.pugx.org/sudiptpa/ipstack/license)](https://packagist.org/packages/sudiptpa/ipstack) +A modern, PSR-based PHP client for the [ipstack](https://ipstack.com) API. -https://ipstack.com provides a public HTTP API for software developers to search the geolocation of IP addresses. It uses a database of IP addresses that are associated to cities along with other relevant information like time zone, latitude and longitude. +## Highlights -You're allowed up to 10,000 queries per month by default. Once this limit is reached, all of your requests will result in HTTP 403, forbidden, until your quota is cleared. +- PSR-18 transport architecture +- Factory-based client construction +- Typed result models (`IpstackResult`, `Country`, `Region`, etc.) +- Bulk lookup support (up to 50 IPs per request) +- Domain exceptions mapped from ipstack API error codes -The ipstack is an API service which enable you to locate and identify website visitors at a stage before any data is entered into your system. The data received from the API can be used to enhance user experiences based on location data and assess risks and potential threats to your web application in time. +## Requirements -### Installation +- PHP `^8.5` +- `psr/http-client` +- `psr/http-factory` +- `psr/http-message` -You can install the package via composer: [Composer](http://getcomposer.org/). +## Installation -``` +```bash composer require sudiptpa/ipstack ``` -And run composer to update your dependencies: +## Architecture + +Core layers: + +- `Ipstack::factory()` configures and builds the client +- `IpstackClient` runs lookup operations +- `TransportInterface` abstracts HTTP transport (`Psr18Transport` included) +- `IpstackResultMapper` maps API payloads to typed models + +Main entry points: + +- `Ipstack\\Ipstack` +- `Ipstack\\Factory\\IpstackFactory` +- `Ipstack\\Client\\IpstackClient` +- `Ipstack\\Client\\Options` + +## Quick Start (PSR-18) + +```php +withAccessKey('YOUR_ACCESS_KEY') + ->withPsr18(new Psr18Client(), new Psr17Factory()) + ->build(); + +$result = $client->lookup('8.8.8.8'); + +echo $result->formatted(); +``` + +## Full Usage Examples + +### 1) Reusable bootstrap + +```php +use Ipstack\Client\IpstackClient; +use Ipstack\Ipstack; +use Nyholm\Psr7\Factory\Psr17Factory; +use Symfony\Component\HttpClient\Psr18Client; + +function ipstackClient(string $accessKey): IpstackClient +{ + return Ipstack::factory() + ->withAccessKey($accessKey) + ->withPsr18(new Psr18Client(), new Psr17Factory()) + ->build(); +} +``` + +### 2) Override base URL (advanced) + +```php +$client = Ipstack::factory() + ->withAccessKey('YOUR_ACCESS_KEY') + ->withBaseUrl('https://api.ipstack.com') + ->withPsr18(new Psr18Client(), new Psr17Factory()) + ->build(); +``` + +### 3) Single IP lookup + options - $ curl -s http://getcomposer.org/installer | php - $ php composer.phar update +```php +use Ipstack\Client\Options; -### Usage +$options = Options::create() + ->fields(['ip', 'country_name', 'region_name', 'city', 'zip']) + ->language('en') + ->security(true) + ->hostname(true); -This package only supports `json` format for now. +$result = $client->lookup('8.8.8.8', $options); -Here are a few examples on how you can use the package: +echo $result->ip . PHP_EOL; +echo $result->formatted() . PHP_EOL; +echo ($result->country->name ?? 'unknown') . PHP_EOL; +``` -#### Free +### 4) Requester IP (`/check`) ```php - $ipstack = new Sujip\Ipstack\Ipstack($ip); +$result = $client->lookupRequester(); + +echo $result->ip . PHP_EOL; +``` - $ipstack->country(); +### 5) Bulk lookup - $ipstack->city(); +```php +$results = $client->lookupBulk(['8.8.8.8', '1.1.1.1']); + +echo 'count=' . count($results) . PHP_EOL; - $ipstack->region(); +foreach ($results as $row) { + echo $row->ip . ' => ' . $row->formatted() . PHP_EOL; +} ``` -#### Using API Key +Notes: + +- Empty list returns an empty `Ipstack\\Model\\IpstackCollection` +- More than 50 IPs throws `Ipstack\\Exception\\IpstackException` + +### 6) Access raw payload and JSON output ```php - $ipstack = new Sujip\Ipstack\Ipstack($ip, $api_key); +$result = $client->lookup('8.8.8.8'); - $ipstack->formatted(); +$raw = $result->raw(); +$json = json_encode($result, JSON_PRETTY_PRINT); + +echo $json . PHP_EOL; ``` -#### Premium Membership +### 7) Custom transport (local smoke test) + +```php +use Ipstack\Ipstack; +use Ipstack\Transport\TransportInterface; + +final class DemoTransport implements TransportInterface +{ + public function get(string $url, array $query): array + { + return [ + 'ip' => '8.8.8.8', + 'country_name' => 'United States', + 'country_code' => 'US', + 'region_name' => 'California', + 'region_code' => 'CA', + 'city' => 'Mountain View', + 'zip' => '94035', + ]; + } +} + +$client = Ipstack::factory() + ->withAccessKey('DUMMY_KEY') + ->withTransport(new DemoTransport()) + ->build(); + +echo $client->lookup('8.8.8.8')->formatted(); +``` -If you have a paid membership with https://ipstack.com and want to make API call with HTTPS mode, you can call ->secure() method. +### 8) Typed exception handling ```php - $ipstack = (new Sujip\Ipstack\Ipstack($ip, $api_key))->secure(); +use Ipstack\Exception\ApiErrorException; +use Ipstack\Exception\BatchNotSupportedException; +use Ipstack\Exception\InvalidFieldsException; +use Ipstack\Exception\InvalidResponseException; +use Ipstack\Exception\IpstackException; +use Ipstack\Exception\RateLimitException; +use Ipstack\Exception\TooManyIpsException; +use Ipstack\Exception\TransportException; + +try { + $result = $client->lookup('8.8.8.8'); +} catch (RateLimitException $e) { + // 104 +} catch (InvalidFieldsException $e) { + // 301 +} catch (TooManyIpsException $e) { + // 302 +} catch (BatchNotSupportedException $e) { + // 303 +} catch (TransportException | InvalidResponseException $e) { + // network/HTTP/JSON transport failure +} catch (ApiErrorException $e) { + // other API-side errors +} catch (IpstackException $e) { + // any other library-level exception +} +``` + +## Models + +`lookup*()` returns `Ipstack\\Model\\IpstackResult` with nested typed objects: + +- `country` (`Country`) +- `region` (`Region`) +- `location` (`Location|null`) +- `connection` (`Connection|null`) +- `security` (`Security|null`) +- `routing` (`Routing|null`) + +Helpers: + +- `$result->formatted()` returns a readable location string +- `$result->raw()` returns original decoded payload +- `json_encode($result)` serializes raw payload (`JsonSerializable`) - $ipstack->formatted(); +## Error Model + +All package exceptions extend `Ipstack\\Exception\\IpstackException`. + +Transport/response exceptions: + +- `TransportException` +- `InvalidResponseException` + +API exceptions: + +- `ApiErrorException` (base) +- `RateLimitException` for code `104` +- `InvalidFieldsException` for code `301` +- `TooManyIpsException` for code `302` +- `BatchNotSupportedException` for code `303` + +## Real API Smoke Test + +Use an environment variable and run this one-liner: + +```bash +IPSTACK_ACCESS_KEY=your_key php -r 'require "vendor/autoload.php"; $c=Ipstack\Ipstack::factory()->withAccessKey(getenv("IPSTACK_ACCESS_KEY"))->withPsr18(new Symfony\Component\HttpClient\Psr18Client(), new Nyholm\Psr7\Factory\Psr17Factory())->build(); echo $c->lookup("8.8.8.8")->formatted(), PHP_EOL;' ``` -Also have a look in the [source code of `Sujip\Ipstack\Ipstack`](https://github.com/sudiptpa/ipstack/blob/master/src/Ipstack.php) to discover the methods you can use. +## Troubleshooting + +- `InvalidArgumentException: Access key is required.` + - Call `->withAccessKey('...')` before `->build()`. +- `InvalidArgumentException: No transport configured...` + - Configure either `->withPsr18(...)` or `->withTransport(...)`. +- `TransportException: Unexpected HTTP status ...` + - Check network access, endpoint, and ipstack key validity. +- `InvalidResponseException: Invalid JSON response` + - Usually an upstream/proxy response issue; inspect raw HTTP response. +- `RateLimitException` (`104`) + - Monthly/request quota reached on your ipstack account. + +## API Plan Notes + +Some ipstack fields/features may depend on plan tier (for example `security`, `hostname`, and parts of connection/routing data). If a field is unavailable on your plan, ipstack may omit it or return an API error. -### Changelog +## Breaking Changes -Please see [CHANGELOG](https://github.com/sudiptpa/ipstack/blob/master/CHANGELOG.md) for more information what has changed recently. +Compared to the legacy API style: -### Contributing +- `Sujip\\Ipstack\\Ipstack` is replaced by `Ipstack\\Ipstack` +- Constructor-style usage is replaced by factory-style configuration +- Legacy root convenience accessors are replaced by typed result objects from lookup methods +- `secure()` is no longer the documented toggle pattern +- Transport wiring is explicit and PSR-based +- Bulk lookup is now `lookupBulk(array $ips)` with a strict max of 50 IPs/request -Contributions are **welcome** and will be fully **credited**. +## Migration Guide (v1 -> v2) -Contributions can be made via a Pull Request on [Github](https://github.com/sudiptpa/ipstack). +Use this quick mapping to migrate legacy usage to the current API. +| v1 (legacy) | v2 (current) | +| --- | --- | +| `new Sujip\\Ipstack\\Ipstack($ip)` | Build once, then call lookup: `Ipstack::factory()->withAccessKey(...)->withPsr18(...)->build()->lookup($ip)` | +| `new Sujip\\Ipstack\\Ipstack($ip, $apiKey)` | `Ipstack::factory()->withAccessKey($apiKey)->withPsr18(...)->build()` | +| `$ipstack->country()` | `$client->lookup($ip)->country->name` | +| `$ipstack->region()` | `$client->lookup($ip)->region->name` | +| `$ipstack->city()` | `$client->lookup($ip)->city` | +| `$ipstack->formatted()` | `$client->lookup($ip)->formatted()` | +| `$ipstack->secure()` | Use configured base URL + transport: `withBaseUrl(...)` + `withPsr18(...)` | +| N/A (or ad-hoc loops) | Native bulk call: `$client->lookupBulk([$ip1, $ip2])` | +| Generic runtime/API failures | Typed exception model (`RateLimitException`, `InvalidFieldsException`, `TransportException`, etc.) | -### Testing +### Suggested migration steps +1. Replace direct constructor usage with factory-based client construction. +2. Create one reusable `IpstackClient` service and inject it where needed. +3. Replace legacy convenience getters with `lookup()` result model access. +4. Add typed exception handling around lookup calls. +5. Add a smoke test (local fake transport + real API env test) before release. + +## Development + +```bash +composer test +composer stan ``` - $ composer test - ``` -### Support +## Author + +- Sujip Thapa (`sudiptpa@gmail.com`) -If you are having general issues with the package, feel free to drop me and email [sudiptpa@gmail.com](mailto:sudiptpa@gmail.com) +## License -If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/sudiptpa/ipstack/issues), -or better yet, fork the library and submit a pull request. +MIT. See `LICENSE`. From c2394cf2a521f8a2842a398dca36b588e77c0ef8 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 16:47:43 +0545 Subject: [PATCH 07/11] Added gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 9c006cf..e0b9a47 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,8 @@ /bin/ composer.lock composer.phar +.phpunit.cache/ +.phpunit.result.cache +coverage/ +*.cache +.DS_Store From 684d41601d8ef92eb216cb4bc9291076724783fe Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 17:08:12 +0545 Subject: [PATCH 08/11] chore: modernize tooling and docs for php 8.3-8.5 --- .github/workflows/ci.yml | 4 ++-- README.md | 11 ++++++++++- composer.json | 15 +++++++++------ phpstan.neon | 4 +++- rector.php | 21 +++++++++++++++++++++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 rector.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d1612e..3ae917e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.5'] + php: ['8.3', '8.4', '8.5'] dependency-version: ['prefer-stable', 'prefer-lowest'] steps: @@ -60,4 +60,4 @@ jobs: run: composer test - name: Run PHPStan - run: composer stan \ No newline at end of file + run: composer stan diff --git a/README.md b/README.md index e612095..f9aedf1 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,11 @@ A modern, PSR-based PHP client for the [ipstack](https://ipstack.com) API. ## Requirements -- PHP `^8.5` +- PHP `8.3` to `8.5` (`>=8.3 <8.6`) - `psr/http-client` - `psr/http-factory` - `psr/http-message` +- A concrete PSR-18 client + PSR-17 factory implementation (for example `symfony/http-client` + `nyholm/psr7`) ## Installation @@ -23,6 +24,12 @@ A modern, PSR-based PHP client for the [ipstack](https://ipstack.com) API. composer require sudiptpa/ipstack ``` +Optional (for the PSR-18 quick-start adapter stack shown below): + +```bash +composer require symfony/http-client nyholm/psr7 +``` + ## Architecture Core layers: @@ -303,6 +310,8 @@ Use this quick mapping to migrate legacy usage to the current API. ```bash composer test composer stan +composer rector +composer rector:check ``` ## Author diff --git a/composer.json b/composer.json index 2dc7582..2c535ee 100644 --- a/composer.json +++ b/composer.json @@ -15,16 +15,17 @@ } ], "require": { - "php": "^8.5", + "php": ">=8.3 <8.6", "psr/http-client": "^1.0", "psr/http-factory": "^1.1", - "psr/http-message": "^2.0", - "symfony/http-client": "^8.0", - "nyholm/psr7": "^1.8" + "psr/http-message": "^2.0" }, "require-dev": { "phpunit/phpunit": "^11.0", - "phpstan/phpstan": "^1.11" + "phpstan/phpstan": "^1.11", + "symfony/http-client": "^7.0 || ^8.0", + "nyholm/psr7": "^1.8", + "rector/rector": "^1.2" }, "autoload": { "psr-4": { @@ -43,7 +44,9 @@ }, "scripts": { "test": "phpunit", - "stan": "phpstan analyse -c phpstan.neon" + "stan": "phpstan analyse -c phpstan.neon --debug", + "rector": "@php vendor/bin/rector process --config=rector.php", + "rector:check": "@php vendor/bin/rector process --config=rector.php --dry-run" }, "minimum-stability": "stable", "prefer-stable": true diff --git a/phpstan.neon b/phpstan.neon index e31ab91..d3be392 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,4 +2,6 @@ parameters: level: 7 paths: - src - - tests \ No newline at end of file + - tests + parallel: + maximumNumberOfProcesses: 1 diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..ae96a82 --- /dev/null +++ b/rector.php @@ -0,0 +1,21 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withPhpVersion(PhpVersion::PHP_83) + ->withSets([ + SetList::CODE_QUALITY, + SetList::TYPE_DECLARATION, + SetList::DEAD_CODE, + LevelSetList::UP_TO_PHP_83, + ]); From 57fa82d5fc4a89af4369d453924bc099530089c0 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 17:15:07 +0545 Subject: [PATCH 09/11] test: harden client, factory, and transport coverage --- .github/workflows/ci.yml | 3 + CHANGELOG.md | 8 ++ tests/Fakes/FakeTransport.php | 4 +- tests/IpstackClientEdgeCaseTest.php | 130 ++++++++++++++++++++++++++++ tests/IpstackFactoryTest.php | 50 +++++++++++ tests/Psr18TransportTest.php | 110 +++++++++++++++++++++++ 6 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 tests/IpstackClientEdgeCaseTest.php create mode 100644 tests/IpstackFactoryTest.php create mode 100644 tests/Psr18TransportTest.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ae917e..318016f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,3 +61,6 @@ jobs: - name: Run PHPStan run: composer stan + + - name: Run Rector (dry-run) + run: composer rector:check diff --git a/CHANGELOG.md b/CHANGELOG.md index 71e19e5..c1e3e20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGE LOG +### v2.1.0 - 2026-02-20 + +- Added production-readiness test coverage for: + - `IpstackClient` requester and bulk edge cases + - `IpstackFactory` configuration failure and success paths + - `Psr18Transport` request building, HTTP error handling, invalid JSON handling, and transport exception wrapping +- Expanded CI quality gates to run `rector:check` in matrix builds. + ### v1.0.0 - 2018-07-06 - New Release diff --git a/tests/Fakes/FakeTransport.php b/tests/Fakes/FakeTransport.php index 048e31d..4a4738b 100644 --- a/tests/Fakes/FakeTransport.php +++ b/tests/Fakes/FakeTransport.php @@ -8,10 +8,10 @@ final class FakeTransport implements TransportInterface { - /** @var array */ + /** @var array */ private array $next; - /** @param array $next */ + /** @param array $next */ public function __construct(array $next) { $this->next = $next; diff --git a/tests/IpstackClientEdgeCaseTest.php b/tests/IpstackClientEdgeCaseTest.php new file mode 100644 index 0000000..44d680b --- /dev/null +++ b/tests/IpstackClientEdgeCaseTest.php @@ -0,0 +1,130 @@ + '127.0.0.1', + 'country_name' => 'Local', + 'region_name' => 'Loopback', + ]), + new IpstackResultMapper() + ); + + $result = $client->lookupRequester(); + + $this->assertSame('127.0.0.1', $result->ip); + $this->assertSame('Local', $result->country->name); + } + + public function testLookupBulkReturnsEmptyCollectionForEmptyInput(): void + { + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + new FakeTransport(['ip' => 'unused']), + new IpstackResultMapper() + ); + + $results = $client->lookupBulk([]); + + $this->assertCount(0, $results); + } + + public function testLookupBulkThrowsWhenMoreThanFiftyIpsAreProvided(): void + { + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + new FakeTransport(['ip' => 'unused']), + new IpstackResultMapper() + ); + + $ips = []; + for ($i = 0; $i < 51; $i++) { + $ips[] = "203.0.113.{$i}"; + } + + $this->expectException(IpstackException::class); + $this->expectExceptionMessage('Bulk lookup supports up to 50 IPs per request.'); + + $client->lookupBulk($ips); + } + + public function testLookupBulkSkipsNonArrayRowsAndMapsArrayRows(): void + { + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + new FakeTransport([ + [ + 'ip' => '8.8.8.8', + 'country_name' => 'United States', + ], + 'ignore-me', + [ + 'ip' => '1.1.1.1', + 'country_name' => 'Australia', + ], + ]), + new IpstackResultMapper() + ); + + $results = $client->lookupBulk(['8.8.8.8', '1.1.1.1']); + + $this->assertCount(2, $results); + $this->assertSame('8.8.8.8', $results->all()[0]->ip); + $this->assertSame('1.1.1.1', $results->all()[1]->ip); + } + + /** + * @dataProvider apiErrorInBulkProvider + * @param class-string<\Throwable> $class + */ + public function testLookupBulkMapsTypedApiErrors(int $code, string $class): void + { + $client = new IpstackClient( + new Config('KEY'), + new Endpoint('https://api.ipstack.com'), + new FakeTransport([ + 'error' => ['code' => $code, 'info' => 'error'], + ]), + new IpstackResultMapper() + ); + + $this->expectException($class); + + $client->lookupBulk(['8.8.8.8']); + } + + /** + * @return array}> + */ + public static function apiErrorInBulkProvider(): array + { + return [ + 'invalid-fields' => [301, InvalidFieldsException::class], + 'too-many-ips' => [302, TooManyIpsException::class], + 'batch-not-supported' => [303, BatchNotSupportedException::class], + ]; + } +} diff --git a/tests/IpstackFactoryTest.php b/tests/IpstackFactoryTest.php new file mode 100644 index 0000000..3927084 --- /dev/null +++ b/tests/IpstackFactoryTest.php @@ -0,0 +1,50 @@ +withTransport(new FakeTransport(['ip' => '8.8.8.8'])); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Access key is required.'); + + $factory->build(); + } + + public function testBuildThrowsWhenTransportIsMissing(): void + { + $factory = (new IpstackFactory()) + ->withAccessKey('KEY'); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('No transport configured.'); + + $factory->build(); + } + + public function testBuildCreatesClientWhenConfigured(): void + { + $factory = (new IpstackFactory()) + ->withAccessKey('KEY') + ->withTransport(new FakeTransport([ + 'ip' => '8.8.8.8', + 'country_name' => 'United States', + ])); + + $client = $factory->build(); + $result = $client->lookup('8.8.8.8'); + + $this->assertSame('8.8.8.8', $result->ip); + $this->assertSame('United States', $result->country->name); + } +} diff --git a/tests/Psr18TransportTest.php b/tests/Psr18TransportTest.php new file mode 100644 index 0000000..82e85bf --- /dev/null +++ b/tests/Psr18TransportTest.php @@ -0,0 +1,110 @@ +createMock(RequestInterface::class); + $requests = $this->createMock(RequestFactoryInterface::class); + $http = $this->createMock(ClientInterface::class); + $response = $this->createMock(ResponseInterface::class); + $stream = $this->createMock(StreamInterface::class); + + $requests->expects($this->once()) + ->method('createRequest') + ->with( + 'GET', + 'https://api.ipstack.com/8.8.8.8?access_key=KEY&language=en' + ) + ->willReturn($request); + + $http->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $response->method('getStatusCode')->willReturn(200); + $response->method('getBody')->willReturn($stream); + $stream->method('__toString')->willReturn('{"ip":"8.8.8.8"}'); + + $transport = new Psr18Transport($http, $requests); + $data = $transport->get('https://api.ipstack.com/8.8.8.8', [ + 'access_key' => 'KEY', + 'language' => 'en', + ]); + + $this->assertSame('8.8.8.8', $data['ip']); + } + + public function testGetThrowsTransportExceptionOnNonSuccessfulStatus(): void + { + $request = $this->createMock(RequestInterface::class); + $requests = $this->createMock(RequestFactoryInterface::class); + $http = $this->createMock(ClientInterface::class); + $response = $this->createMock(ResponseInterface::class); + + $requests->method('createRequest')->willReturn($request); + $http->method('sendRequest')->willReturn($response); + $response->method('getStatusCode')->willReturn(403); + + $transport = new Psr18Transport($http, $requests); + + $this->expectException(TransportException::class); + $this->expectExceptionMessage('Unexpected HTTP status: 403'); + + $transport->get('https://api.ipstack.com/8.8.8.8', ['access_key' => 'KEY']); + } + + public function testGetThrowsInvalidResponseExceptionWhenJsonIsInvalid(): void + { + $request = $this->createMock(RequestInterface::class); + $requests = $this->createMock(RequestFactoryInterface::class); + $http = $this->createMock(ClientInterface::class); + $response = $this->createMock(ResponseInterface::class); + $stream = $this->createMock(StreamInterface::class); + + $requests->method('createRequest')->willReturn($request); + $http->method('sendRequest')->willReturn($response); + $response->method('getStatusCode')->willReturn(200); + $response->method('getBody')->willReturn($stream); + $stream->method('__toString')->willReturn('not-json'); + + $transport = new Psr18Transport($http, $requests); + + $this->expectException(InvalidResponseException::class); + $this->expectExceptionMessage('Invalid JSON response'); + + $transport->get('https://api.ipstack.com/8.8.8.8', ['access_key' => 'KEY']); + } + + public function testGetWrapsUnderlyingClientThrowable(): void + { + $request = $this->createMock(RequestInterface::class); + $requests = $this->createMock(RequestFactoryInterface::class); + $http = $this->createMock(ClientInterface::class); + + $requests->method('createRequest')->willReturn($request); + $http->method('sendRequest')->willThrowException(new \RuntimeException('network down')); + + $transport = new Psr18Transport($http, $requests); + + $this->expectException(TransportException::class); + $this->expectExceptionMessage('HTTP request failed: network down'); + + $transport->get('https://api.ipstack.com/8.8.8.8', ['access_key' => 'KEY']); + } +} From 3f9b40b2e44258ea81a6f0c73c923a341926a412 Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 17:21:01 +0545 Subject: [PATCH 10/11] docs: add quality gates and changelog pointers --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index f9aedf1..ae0867f 100644 --- a/README.md +++ b/README.md @@ -305,6 +305,14 @@ Use this quick mapping to migrate legacy usage to the current API. 4. Add typed exception handling around lookup calls. 5. Add a smoke test (local fake transport + real API env test) before release. +## Quality Gates + +CI runs the following checks across PHP `8.3`, `8.4`, and `8.5`: + +- `composer test` +- `composer stan` +- `composer rector:check` + ## Development ```bash @@ -314,6 +322,10 @@ composer rector composer rector:check ``` +## Changelog + +See `CHANGELOG.md` for release notes (latest hardening release: `v2.1.0`). + ## Author - Sujip Thapa (`sudiptpa@gmail.com`) From 15265b513d26659bfa97aada3dc9ced3dc5e0b7e Mon Sep 17 00:00:00 2001 From: Sujip Thapa Date: Fri, 20 Feb 2026 17:27:11 +0545 Subject: [PATCH 11/11] ci: stabilize matrix by limiting static checks to prefer-stable --- .github/workflows/ci.yml | 4 +--- README.md | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 318016f..f05dac3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,5 @@ jobs: run: composer test - name: Run PHPStan + if: matrix.dependency-version == 'prefer-stable' run: composer stan - - - name: Run Rector (dry-run) - run: composer rector:check diff --git a/README.md b/README.md index ae0867f..4d41fb6 100644 --- a/README.md +++ b/README.md @@ -310,8 +310,7 @@ Use this quick mapping to migrate legacy usage to the current API. CI runs the following checks across PHP `8.3`, `8.4`, and `8.5`: - `composer test` -- `composer stan` -- `composer rector:check` +- `composer stan` (on `prefer-stable` matrix jobs) ## Development