From ad3e8c3a6789343f590c6856bac6ebcec7f954ae Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Fri, 25 Apr 2025 22:09:07 +0700 Subject: [PATCH 01/42] update ubuntu runner version --- .github/workflows/php.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 425901b..6e6b5c3 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -12,15 +12,15 @@ permissions: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - name: Set up PHP 8.0 + - name: Set up PHP 8.3 uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.3 - name: Install librdkafka and rdkafka extension run: | From ad228b965b0732898efee8ce4467fb1f452f3a71 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Sun, 27 Apr 2025 13:26:54 +0700 Subject: [PATCH 02/42] client external mock mapping --- composer.json | 17 +- composer.lock | 2906 ++++++++++------- phpcs.xml | 24 + phpunit.xml | 1 - src/Commands/Command.php | 9 + src/Commands/DtoMakeCommand.php | 10 - src/Commands/stubs/dto.plain.stub | 6 +- src/Dtos/TraitConvertibleDtos.php | 2 +- src/Dtos/TraitDtos.php | 5 +- src/Dtos/TypeConverter.php | 4 +- src/Exceptions/AccessException.php | 2 +- src/Exceptions/DataNotFoundException.php | 2 +- src/Exceptions/Handler.php | 17 +- src/Exceptions/HeaderException.php | 2 +- src/Exceptions/InvalidRuleException.php | 2 +- src/Exceptions/ParameterException.php | 2 +- src/Exceptions/RuntimeException.php | 2 +- src/Exceptions/StdException.php | 10 +- src/Exceptions/ThirdPartyServiceException.php | 2 +- src/Exceptions/UnsupportedException.php | 2 +- src/Exceptions/WaitingException.php | 2 +- src/Facades/Queue.php | 1 - src/Libraries/Client.php | 63 +- src/Libraries/ClientExternal.php | 88 +- src/Libraries/Kafka.php | 251 -- src/Libraries/KafkaCallable.php | 178 - src/Logs/Runtime.php | 4 +- src/Logs/TraitLog.php | 2 +- src/Middlewares/ActivityMonitor.php | 12 +- src/Responses/StdResponse.php | 3 +- src/Services/Context.php | 7 +- tests/Libraries/ClientExternalTest.php | 27 +- tests/Libraries/ClientTest.php | 16 +- tests/Logs/LogTest.php | 2 + 34 files changed, 1966 insertions(+), 1717 deletions(-) delete mode 100644 src/Libraries/Kafka.php delete mode 100644 src/Libraries/KafkaCallable.php diff --git a/composer.json b/composer.json index 4a5276e..f04c445 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,10 @@ "license": "MIT", "type": "library", "require": { - "php": "^7.3|^8.0", - "laravel/lumen-framework": "^8.0", - "jobcloud/php-kafka-lib": "^1.7", - "flix-tech/avro-serde-php": "^1.7" + "php": "^8.3", + "laravel/lumen-framework": "11.2.0", + "jobcloud/php-kafka-lib": "2.0.0", + "flix-tech/avro-serde-php": "2.1" }, "autoload": { "psr-4": { @@ -25,10 +25,17 @@ "require-dev": { "squizlabs/php_codesniffer": "*", "phpunit/phpunit": "9.6.20", - "rregeer/phpunit-coverage-check": "^0.3.1" + "rregeer/phpunit-coverage-check": "^0.3.1", + "slevomat/coding-standard": "^8.15", + "mockery/mockery": "^1.6" }, "scripts": { "lint": "./vendor/bin/phpcs -p", "test": "./vendor/bin/phpunit --configuration phpunit.xml --coverage-clover report_coverage.xml && php prepare-coverage-report.php && ./vendor/bin/coverage-check report_coverage.xml 40" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/composer.lock b/composer.lock index 92a13af..35f826d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "03f24aa429cdf0dfb137515c3c8888c6", + "content-hash": "aba7f2e37d8383c8dcc95f47f9dfd30b", "packages": [ { "name": "beberlei/assert", - "version": "v3.3.2", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/beberlei/assert.git", - "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655" + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beberlei/assert/zipball/cb70015c04be1baee6f5f5c953703347c0ac1655", - "reference": "cb70015c04be1baee6f5f5c953703347c0ac1655", + "url": "https://api.github.com/repos/beberlei/assert/zipball/b5fd8eacd8915a1b627b8bfc027803f1939734dd", + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd", "shasum": "" }, "require": { @@ -25,7 +25,7 @@ "ext-json": "*", "ext-mbstring": "*", "ext-simplexml": "*", - "php": "^7.0 || ^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", @@ -69,31 +69,31 @@ ], "support": { "issues": "https://github.com/beberlei/assert/issues", - "source": "https://github.com/beberlei/assert/tree/v3.3.2" + "source": "https://github.com/beberlei/assert/tree/v3.3.3" }, - "time": "2021-12-16T21:41:27+00:00" + "time": "2024-07-15T13:18:35+00:00" }, { "name": "brick/math", - "version": "0.11.0", + "version": "0.12.3", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", "shasum": "" }, "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^9.0", - "vimeo/psalm": "5.0.0" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" }, "type": "library", "autoload": { @@ -113,12 +113,17 @@ "arithmetic", "bigdecimal", "bignum", + "bignumber", "brick", - "math" + "decimal", + "integer", + "math", + "mathematics", + "rational" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.11.0" + "source": "https://github.com/brick/math/tree/0.12.3" }, "funding": [ { @@ -126,30 +131,30 @@ "type": "github" } ], - "time": "2023-01-15T23:15:59+00:00" + "time": "2025-02-28T13:11:00+00:00" }, { "name": "carbonphp/carbon-doctrine-types", - "version": "2.1.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", - "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", - "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "conflict": { - "doctrine/dbal": "<3.7.0 || >=4.0.0" + "doctrine/dbal": "<4.0.0 || >=5.0.0" }, "require-dev": { - "doctrine/dbal": "^3.7.0", + "doctrine/dbal": "^4.0.0", "nesbot/carbon": "^2.71.0 || ^3.0.0", "phpunit/phpunit": "^10.3" }, @@ -179,7 +184,7 @@ ], "support": { "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", - "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" }, "funding": [ { @@ -195,7 +200,7 @@ "type": "tidelift" } ], - "time": "2023-12-11T17:09:12+00:00" + "time": "2024-02-09T16:56:22+00:00" }, { "name": "doctrine/inflector", @@ -290,31 +295,32 @@ }, { "name": "doctrine/lexer", - "version": "1.2.3", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -346,7 +352,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -362,7 +368,7 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "dragonmantank/cron-expression", @@ -431,27 +437,26 @@ }, { "name": "egulias/email-validator", - "version": "2.1.25", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { - "doctrine/lexer": "^1.0.1", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.10" + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "dominicsayers/isemail": "^3.0.7", - "phpunit/phpunit": "^4.8.36|^7.5.15", - "satooshi/php-coveralls": "^1.0.1" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -459,7 +464,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -487,7 +492,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" }, "funding": [ { @@ -495,27 +500,27 @@ "type": "github" } ], - "time": "2020-12-29T14:50:06+00:00" + "time": "2025-03-06T22:45:56+00:00" }, { "name": "flix-tech/avro-php", - "version": "4.3.0", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/flix-tech/avro-php.git", - "reference": "5936698fab7d3593ef73b6632f2c0d07ba2267f6" + "reference": "1d537bfe4ecab405917d15eee8f2020743fc8596" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/avro-php/zipball/5936698fab7d3593ef73b6632f2c0d07ba2267f6", - "reference": "5936698fab7d3593ef73b6632f2c0d07ba2267f6", + "url": "https://api.github.com/repos/flix-tech/avro-php/zipball/1d537bfe4ecab405917d15eee8f2020743fc8596", + "reference": "1d537bfe4ecab405917d15eee8f2020743fc8596", "shasum": "" }, "require": { - "php": ">=7.4|>=8.0" + "php": "^8.1" }, "require-dev": { - "phpunit/phpunit": "~8.5" + "phpunit/phpunit": "^10.5" }, "suggest": { "ext-gmp": "Large integer support for 32-bit platforms.", @@ -534,36 +539,37 @@ ], "description": "Avro schema encoder/decoder. Fork of rg/avro-php", "support": { - "source": "https://github.com/flix-tech/avro-php/tree/4.3.0" + "source": "https://github.com/flix-tech/avro-php/tree/5.1.1" }, - "time": "2022-08-10T07:34:07+00:00" + "time": "2025-01-24T05:04:07+00:00" }, { "name": "flix-tech/avro-serde-php", - "version": "1.7.2", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/flix-tech/avro-serde-php.git", - "reference": "b6b6baaf01a54d314ed957598c0740064b572aad" + "reference": "ffeab369fe3631d2a076ef9744f0ee2dcab2238c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/avro-serde-php/zipball/b6b6baaf01a54d314ed957598c0740064b572aad", - "reference": "b6b6baaf01a54d314ed957598c0740064b572aad", + "url": "https://api.github.com/repos/flix-tech/avro-serde-php/zipball/ffeab369fe3631d2a076ef9744f0ee2dcab2238c", + "reference": "ffeab369fe3631d2a076ef9744f0ee2dcab2238c", "shasum": "" }, "require": { "beberlei/assert": "^2.9.9|~3.0", - "flix-tech/avro-php": "^4.1.0", - "flix-tech/confluent-schema-registry-api": "^7.3.1", - "guzzlehttp/promises": "^1.4.0", + "flix-tech/avro-php": "^5.0", + "flix-tech/confluent-schema-registry-api": "^8.0", + "guzzlehttp/promises": "^1.4.0|^2.0.0", "php": "^7.3|^8.0", "widmogrod/php-functional": "^6.0" }, "require-dev": { "doctrine/annotations": "^1.11", "phpbench/phpbench": "1.0.0-alpha2", - "phpunit/phpunit": "^8.2.3|^9.4.2", + "phpunit/phpunit": "^9.4.2", + "roave/security-advisories": "dev-latest", "symfony/serializer": "^3.4|^4.3", "vlucas/phpdotenv": "~2.4" }, @@ -574,8 +580,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev", - "dev-1.x": "1.x-dev" + "dev-1.x": "1.x-dev", + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -615,33 +621,33 @@ ], "support": { "issues": "https://github.com/flix-tech/avro-serde-php/issues", - "source": "https://github.com/flix-tech/avro-serde-php/tree/1.7.2" + "source": "https://github.com/flix-tech/avro-serde-php/tree/2.1.0" }, - "time": "2022-06-30T14:21:32+00:00" + "time": "2024-01-26T13:39:27+00:00" }, { "name": "flix-tech/confluent-schema-registry-api", - "version": "7.6.1", + "version": "8.1.0", "source": { "type": "git", "url": "https://github.com/flix-tech/schema-registry-php-client.git", - "reference": "89817110145f6bc4690bbeb190c3e5b4f733ba12" + "reference": "87023aebb0393da62d932b9be49d0d891a52ae37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/schema-registry-php-client/zipball/89817110145f6bc4690bbeb190c3e5b4f733ba12", - "reference": "89817110145f6bc4690bbeb190c3e5b4f733ba12", + "url": "https://api.github.com/repos/flix-tech/schema-registry-php-client/zipball/87023aebb0393da62d932b9be49d0d891a52ae37", + "reference": "87023aebb0393da62d932b9be49d0d891a52ae37", "shasum": "" }, "require": { "beberlei/assert": "~2.7|~3.0", "ext-curl": "*", "ext-json": "*", - "flix-tech/avro-php": "^4.3", + "flix-tech/avro-php": "^5.0", "guzzlehttp/guzzle": "^7.0", - "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/promises": "^1.4.0|^2.0.0", "guzzlehttp/psr7": "^1.7|^2.1", - "php": "^7.4|^8.0|^8.1" + "php": "^7.4|^8.0" }, "require-dev": { "doctrine/cache": "~1.3", @@ -679,22 +685,93 @@ "description": "A PHP 7.4+ library to consume the Confluent Schema Registry REST API.", "support": { "issues": "https://github.com/flix-tech/schema-registry-php-client/issues", - "source": "https://github.com/flix-tech/schema-registry-php-client/tree/7.6.1" + "source": "https://github.com/flix-tech/schema-registry-php-client/tree/8.1.0" + }, + "time": "2024-01-26T13:22:35+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } }, - "time": "2022-08-24T08:12:15+00:00" + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" }, { "name": "functional-php/fantasy-land", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/functional-php/fantasy-land.git", - "reference": "1e2366e68057bbc7a65d58dd663324eb9b299775" + "reference": "9a43201d827ced038ffd374f2d018d7a54ad33e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/functional-php/fantasy-land/zipball/1e2366e68057bbc7a65d58dd663324eb9b299775", - "reference": "1e2366e68057bbc7a65d58dd663324eb9b299775", + "url": "https://api.github.com/repos/functional-php/fantasy-land/zipball/9a43201d827ced038ffd374f2d018d7a54ad33e2", + "reference": "9a43201d827ced038ffd374f2d018d7a54ad33e2", "shasum": "" }, "require": { @@ -727,9 +804,9 @@ "description": "Specification for interoperability of common algebraic structures in PHP", "support": { "issues": "https://github.com/functional-php/fantasy-land/issues", - "source": "https://github.com/functional-php/fantasy-land/tree/1.0.1" + "source": "https://github.com/functional-php/fantasy-land/tree/1.0.2" }, - "time": "2021-01-19T18:06:19+00:00" + "time": "2024-12-18T16:28:32+00:00" }, { "name": "graham-campbell/result-type", @@ -795,16 +872,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.9.2", + "version": "7.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", "shasum": "" }, "require": { @@ -901,7 +978,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" }, "funding": [ { @@ -917,33 +994,37 @@ "type": "tidelift" } ], - "time": "2024-07-24T11:22:20+00:00" + "time": "2025-03-27T13:37:11+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.3", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -980,7 +1061,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.3" + "source": "https://github.com/guzzle/promises/tree/2.2.0" }, "funding": [ { @@ -996,20 +1077,20 @@ "type": "tidelift" } ], - "time": "2023-05-21T12:31:43+00:00" + "time": "2025-03-27T13:27:01+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.0", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", "shasum": "" }, "require": { @@ -1096,7 +1177,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.0" + "source": "https://github.com/guzzle/psr7/tree/2.7.1" }, "funding": [ { @@ -1112,40 +1193,127 @@ "type": "tidelift" } ], - "time": "2024-07-18T11:15:46+00:00" + "time": "2025-03-27T12:30:47+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-02-03T10:55:03+00:00" }, { "name": "illuminate/auth", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/auth.git", - "reference": "28e3e57f777685018374bb59bbaa54598dbdf441" + "reference": "da681d377fcd145ff61d82d809e5986b03226e75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/auth/zipball/28e3e57f777685018374bb59bbaa54598dbdf441", - "reference": "28e3e57f777685018374bb59bbaa54598dbdf441", + "url": "https://api.github.com/repos/illuminate/auth/zipball/da681d377fcd145ff61d82d809e5986b03226e75", + "reference": "da681d377fcd145ff61d82d809e5986b03226e75", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/http": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/queue": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "ext-hash": "*", + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/http": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/queue": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "suggest": { - "illuminate/console": "Required to use the auth:clear-resets command (^8.0).", - "illuminate/queue": "Required to fire login / logout events (^8.0).", - "illuminate/session": "Required to use the session based guard (^8.0)." + "illuminate/console": "Required to use the auth:clear-resets command (^11.0).", + "illuminate/queue": "Required to fire login / logout events (^11.0).", + "illuminate/session": "Required to use the session based guard (^11.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1169,40 +1337,41 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-09-21T21:30:03+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/broadcasting", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/broadcasting.git", - "reference": "d7c0c81bcc679c294746b161f4b834997e904cf4" + "reference": "2980909486df6a4d5a26d979edda20200982822f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/broadcasting/zipball/d7c0c81bcc679c294746b161f4b834997e904cf4", - "reference": "d7c0c81bcc679c294746b161f4b834997e904cf4", + "url": "https://api.github.com/repos/illuminate/broadcasting/zipball/2980909486df6a4d5a26d979edda20200982822f", + "reference": "2980909486df6a4d5a26d979edda20200982822f", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/bus": "^8.0", - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/queue": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "psr/log": "^1.0|^2.0" + "illuminate/bus": "^11.0", + "illuminate/collections": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/queue": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2", + "psr/log": "^1.0|^2.0|^3.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0|^7.0)." + "ext-hash": "Required to use the Ably and Pusher broadcast drivers.", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1226,28 +1395,28 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-06T14:28:26+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/bus", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/bus.git", - "reference": "d2a8ae4bfd881086e55455e470776358eab27eae" + "reference": "5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/bus/zipball/d2a8ae4bfd881086e55455e470776358eab27eae", - "reference": "d2a8ae4bfd881086e55455e470776358eab27eae", + "url": "https://api.github.com/repos/illuminate/bus/zipball/5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3", + "reference": "5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/pipeline": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/pipeline": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "suggest": { "illuminate/queue": "Required to use closures when chaining jobs (^7.0)." @@ -1255,7 +1424,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1279,43 +1448,45 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-03-07T15:02:42+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/cache", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/cache.git", - "reference": "7ae5b3661413dad7264b5c69037190d766bae50f" + "reference": "f9196623f6b75f7e69b9ac92f367491909753987" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/cache/zipball/7ae5b3661413dad7264b5c69037190d766bae50f", - "reference": "7ae5b3661413dad7264b5c69037190d766bae50f", + "url": "https://api.github.com/repos/illuminate/cache/zipball/f9196623f6b75f7e69b9ac92f367491909753987", + "reference": "f9196623f6b75f7e69b9ac92f367491909753987", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "provide": { - "psr/simple-cache-implementation": "1.0" + "psr/simple-cache-implementation": "1.0|2.0|3.0" }, "suggest": { + "ext-apcu": "Required to use the APC cache driver.", + "ext-filter": "Required to use the DynamoDb cache driver.", "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^8.0).", - "illuminate/filesystem": "Required to use the file cache driver (^8.0).", - "illuminate/redis": "Required to use the redis cache driver (^8.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.4)." + "illuminate/database": "Required to use the database cache driver (^11.0).", + "illuminate/filesystem": "Required to use the file cache driver (^11.0).", + "illuminate/redis": "Required to use the redis cache driver (^11.0).", + "symfony/cache": "Required to use PSR-6 cache bridge (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1339,38 +1510,40 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-07-22T14:58:32+00:00" + "time": "2025-01-27T22:47:27+00:00" }, { "name": "illuminate/collections", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "705a4e1ef93cd492c45b9b3e7911cccc990a07f4" + "reference": "856b1da953e46281ba61d7c82d337072d3ee1825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/705a4e1ef93cd492c45b9b3e7911cccc990a07f4", - "reference": "705a4e1ef93cd492c45b9b3e7911cccc990a07f4", + "url": "https://api.github.com/repos/illuminate/collections/zipball/856b1da953e46281ba61d7c82d337072d3ee1825", + "reference": "856b1da953e46281ba61d7c82d337072d3ee1825", "shasum": "" }, "require": { - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "php": "^7.3|^8.0" + "illuminate/conditionable": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "php": "^8.2" }, "suggest": { - "symfony/var-dumper": "Required to use the dump method (^5.4)." + "symfony/var-dumper": "Required to use the dump method (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { "files": [ + "functions.php", "helpers.php" ], "psr-4": { @@ -1393,31 +1566,77 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-06-23T15:29:49+00:00" + "time": "2025-03-24T11:54:20+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v11.44.7", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "319b717e0587bd7c8a3b44464f0e27867b4bcda9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/319b717e0587bd7c8a3b44464f0e27867b4bcda9", + "reference": "319b717e0587bd7c8a3b44464f0e27867b4bcda9", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/config", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", - "reference": "feac56ab7a5c70cf2dc60dffe4323eb9851f51a8" + "reference": "64daa8d520cd76e505a82460a672692c56a07be8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/config/zipball/feac56ab7a5c70cf2dc60dffe4323eb9851f51a8", - "reference": "feac56ab7a5c70cf2dc60dffe4323eb9851f51a8", + "url": "https://api.github.com/repos/illuminate/config/zipball/64daa8d520cd76e505a82460a672692c56a07be8", + "reference": "64daa8d520cd76e505a82460a672692c56a07be8", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "php": "^7.3|^8.0" + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1441,43 +1660,49 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-31T15:57:46+00:00" + "time": "2024-11-14T17:17:02+00:00" }, { "name": "illuminate/console", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/console.git", - "reference": "4aaa93223eb3bd8119157c95f58c022967826035" + "reference": "b60225f4f8aa52b015300b581436627e71ce1b18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/console/zipball/4aaa93223eb3bd8119157c95f58c022967826035", - "reference": "4aaa93223eb3bd8119157c95f58c022967826035", + "url": "https://api.github.com/repos/illuminate/console/zipball/b60225f4f8aa52b015300b581436627e71ce1b18", + "reference": "b60225f4f8aa52b015300b581436627e71ce1b18", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "symfony/console": "^5.4", - "symfony/process": "^5.4" + "ext-mbstring": "*", + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "illuminate/view": "^11.0", + "laravel/prompts": "^0.1.20|^0.2|^0.3", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "symfony/console": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3" }, "suggest": { - "dragonmantank/cron-expression": "Required to use scheduler (^3.0.2).", - "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.5.5|^7.0.1).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^8.0).", - "illuminate/container": "Required to use the scheduler (^8.0).", - "illuminate/filesystem": "Required to use the generator command (^8.0).", - "illuminate/queue": "Required to use closures for scheduled jobs (^8.0)." + "dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).", + "ext-pcntl": "Required to use signal trapping.", + "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).", + "illuminate/bus": "Required to use the scheduled job dispatcher (^11.0).", + "illuminate/container": "Required to use the scheduler (^11.0).", + "illuminate/filesystem": "Required to use the generator command (^11.0).", + "illuminate/queue": "Required to use closures for scheduled jobs (^11.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1501,34 +1726,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-04-21T22:14:18+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/container", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "14062628d05f75047c5a1360b9350028427d568e" + "reference": "79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/14062628d05f75047c5a1360b9350028427d568e", - "reference": "14062628d05f75047c5a1360b9350028427d568e", + "url": "https://api.github.com/repos/illuminate/container/zipball/79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a", + "reference": "79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a", "shasum": "" }, "require": { - "illuminate/contracts": "^8.0", - "php": "^7.3|^8.0", - "psr/container": "^1.0" + "illuminate/contracts": "^11.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1" }, "provide": { - "psr/container-implementation": "1.0" + "psr/container-implementation": "1.1|2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1552,31 +1777,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-02-02T21:03:35+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/contracts", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "5e0fd287a1b22a6b346a9f7cd484d8cf0234585d" + "reference": "4b2a67d1663f50085bc91e6371492697a5d2d4e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/5e0fd287a1b22a6b346a9f7cd484d8cf0234585d", - "reference": "5e0fd287a1b22a6b346a9f7cd484d8cf0234585d", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/4b2a67d1663f50085bc91e6371492697a5d2d4e8", + "reference": "4b2a67d1663f50085bc91e6371492697a5d2d4e8", "shasum": "" }, "require": { - "php": "^7.3|^8.0", - "psr/container": "^1.0", - "psr/simple-cache": "^1.0" + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1600,45 +1825,46 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-13T14:47:47+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/database", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "1a5b0e4e6913415464fa2aab554a38b9e6fa44b1" + "reference": "0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/1a5b0e4e6913415464fa2aab554a38b9e6fa44b1", - "reference": "1a5b0e4e6913415464fa2aab554a38b9e6fa44b1", + "url": "https://api.github.com/repos/illuminate/database/zipball/0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2", + "reference": "0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "symfony/console": "^5.4" + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "ext-pdo": "*", + "illuminate/collections": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "laravel/serializable-closure": "^1.3|^2.0", + "php": "^8.2" }, "suggest": { - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", - "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", - "illuminate/console": "Required to use the database commands (^8.0).", - "illuminate/events": "Required to use the observers with Eloquent (^8.0).", - "illuminate/filesystem": "Required to use the migrations (^8.0).", - "illuminate/pagination": "Required to paginate the result set (^8.0).", - "symfony/finder": "Required to use Eloquent model factories (^5.4)." + "ext-filter": "Required to use the Postgres database driver.", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.24).", + "illuminate/console": "Required to use the database commands (^11.0).", + "illuminate/events": "Required to use the observers with Eloquent (^11.0).", + "illuminate/filesystem": "Required to use the migrations (^11.0).", + "illuminate/pagination": "Required to paginate the result set (^11.0).", + "symfony/finder": "Required to use Eloquent model factories (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1668,34 +1894,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-08-31T16:16:06+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/encryption", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/encryption.git", - "reference": "00280dc6aa204b1b6c6d4bf75936d122bd856c15" + "reference": "abd46d355466be65648f1f2503076d204037d699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/encryption/zipball/00280dc6aa204b1b6c6d4bf75936d122bd856c15", - "reference": "00280dc6aa204b1b6c6d4bf75936d122bd856c15", + "url": "https://api.github.com/repos/illuminate/encryption/zipball/abd46d355466be65648f1f2503076d204037d699", + "reference": "abd46d355466be65648f1f2503076d204037d699", "shasum": "" }, "require": { - "ext-json": "*", + "ext-hash": "*", "ext-mbstring": "*", "ext-openssl": "*", - "illuminate/contracts": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/contracts": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1719,35 +1945,35 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-03-14T18:47:47+00:00" + "time": "2024-06-28T20:15:08+00:00" }, { "name": "illuminate/events", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", - "reference": "b7f06cafb6c09581617f2ca05d69e9b159e5a35d" + "reference": "b72dab66d8e05d22dc5aa949efec150bbc73e827" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/b7f06cafb6c09581617f2ca05d69e9b159e5a35d", - "reference": "b7f06cafb6c09581617f2ca05d69e9b159e5a35d", + "url": "https://api.github.com/repos/illuminate/events/zipball/b72dab66d8e05d22dc5aa949efec150bbc73e827", + "reference": "b72dab66d8e05d22dc5aa949efec150bbc73e827", "shasum": "" }, "require": { - "illuminate/bus": "^8.0", - "illuminate/collections": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/bus": "^11.0", + "illuminate/collections": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1774,48 +2000,53 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-09-15T14:32:50+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/filesystem", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", - "reference": "73db3e9a233ed587ba54f52ab8580f3c7bc872b2" + "reference": "d1f217b75ee193bbe27f31df8a94ff6759f31469" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/filesystem/zipball/73db3e9a233ed587ba54f52ab8580f3c7bc872b2", - "reference": "73db3e9a233ed587ba54f52ab8580f3c7bc872b2", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/d1f217b75ee193bbe27f31df8a94ff6759f31469", + "reference": "d1f217b75ee193bbe27f31df8a94ff6759f31469", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "symfony/finder": "^5.4" + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2", + "symfony/finder": "^7.0.3" }, "suggest": { + "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-hash": "Required to use the Filesystem class.", "illuminate/http": "Required for handling uploaded files (^7.0).", - "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.1).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", - "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", - "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", + "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^5.4).", - "symfony/mime": "Required to enable support for guessing extensions (^5.4)." + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", + "symfony/mime": "Required to enable support for guessing extensions (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { + "files": [ + "functions.php" + ], "psr-4": { "Illuminate\\Filesystem\\": "" } @@ -1836,31 +2067,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-15T15:00:40+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/hashing", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/hashing.git", - "reference": "2617f4de8d0150a3f8641b086fafac8c1e0cdbf2" + "reference": "5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/hashing/zipball/2617f4de8d0150a3f8641b086fafac8c1e0cdbf2", - "reference": "2617f4de8d0150a3f8641b086fafac8c1e0cdbf2", + "url": "https://api.github.com/repos/illuminate/hashing/zipball/5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93", + "reference": "5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93", "shasum": "" }, "require": { - "illuminate/contracts": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/contracts": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1884,41 +2115,44 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-10-22T13:20:42+00:00" + "time": "2025-02-14T15:36:00+00:00" }, { "name": "illuminate/http", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/http.git", - "reference": "38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4" + "reference": "383df4e480dbd6272cc0d87fc8206b6405b1b9d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/http/zipball/38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4", - "reference": "38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4", + "url": "https://api.github.com/repos/illuminate/http/zipball/383df4e480dbd6272cc0d87fc8206b6405b1b9d8", + "reference": "383df4e480dbd6272cc0d87fc8206b6405b1b9d8", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/session": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "symfony/http-foundation": "^5.4", - "symfony/http-kernel": "^5.4", - "symfony/mime": "^5.4" + "ext-filter": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "illuminate/collections": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/session": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2", + "symfony/http-foundation": "^7.0.3", + "symfony/http-kernel": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31" }, "suggest": { - "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", - "guzzlehttp/guzzle": "Required to use the HTTP Client (^6.5.5|^7.0.1)." + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image()." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1942,32 +2176,36 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-06-10T18:50:29+00:00" + "time": "2025-03-24T11:58:51+00:00" }, { "name": "illuminate/log", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/log.git", - "reference": "1dbdc6aca24d1d2b5903f865bb206039d4b800b2" + "reference": "73bcd8423739c751442b7e618153c73f78e844cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/log/zipball/1dbdc6aca24d1d2b5903f865bb206039d4b800b2", - "reference": "1dbdc6aca24d1d2b5903f865bb206039d4b800b2", + "url": "https://api.github.com/repos/illuminate/log/zipball/73bcd8423739c751442b7e618153c73f78e844cd", + "reference": "73bcd8423739c751442b7e618153c73f78e844cd", "shasum": "" }, "require": { - "illuminate/contracts": "^8.0", - "illuminate/support": "^8.0", - "monolog/monolog": "^2.0", - "php": "^7.3|^8.0" + "illuminate/contracts": "^11.0", + "illuminate/support": "^11.0", + "monolog/monolog": "^3.0", + "php": "^8.2", + "psr/log": "^1.0|^2.0|^3.0" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -1991,29 +2229,29 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-10T15:22:22+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/macroable", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", - "reference": "aed81891a6e046fdee72edd497f822190f61c162" + "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/macroable/zipball/aed81891a6e046fdee72edd497f822190f61c162", - "reference": "aed81891a6e046fdee72edd497f822190f61c162", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", + "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2037,33 +2275,33 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-11-16T13:57:03+00:00" + "time": "2024-06-28T20:10:30+00:00" }, { "name": "illuminate/pagination", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/pagination.git", - "reference": "16fe8dc35f9d18c58a3471469af656a02e9ab692" + "reference": "2c4970463f7ede55be207fbdc27608b4c4178380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/pagination/zipball/16fe8dc35f9d18c58a3471469af656a02e9ab692", - "reference": "16fe8dc35f9d18c58a3471469af656a02e9ab692", + "url": "https://api.github.com/repos/illuminate/pagination/zipball/2c4970463f7ede55be207fbdc27608b4c4178380", + "reference": "2c4970463f7ede55be207fbdc27608b4c4178380", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "ext-filter": "*", + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2087,31 +2325,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-06-27T13:26:06+00:00" + "time": "2025-02-14T15:33:00+00:00" }, { "name": "illuminate/pipeline", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/pipeline.git", - "reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2" + "reference": "f73bb7cab13ac8ef91094dc46976f5e992eea127" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2", - "reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2", + "url": "https://api.github.com/repos/illuminate/pipeline/zipball/f73bb7cab13ac8ef91094dc46976f5e992eea127", + "reference": "f73bb7cab13ac8ef91094dc46976f5e992eea127", "shasum": "" }, "require": { - "illuminate/contracts": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/contracts": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2135,49 +2373,50 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-03-26T18:39:16+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/queue", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/queue.git", - "reference": "0023daabf67743f7a2bd8328ca2b5537d93e4ae7" + "reference": "55b305a48a1325f30e2e23f879f5a7e7ee8b54cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/queue/zipball/0023daabf67743f7a2bd8328ca2b5537d93e4ae7", - "reference": "0023daabf67743f7a2bd8328ca2b5537d93e4ae7", + "url": "https://api.github.com/repos/illuminate/queue/zipball/55b305a48a1325f30e2e23f879f5a7e7ee8b54cf", + "reference": "55b305a48a1325f30e2e23f879f5a7e7ee8b54cf", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/console": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/database": "^8.0", - "illuminate/filesystem": "^8.0", - "illuminate/pipeline": "^8.0", - "illuminate/support": "^8.0", - "laravel/serializable-closure": "^1.0", - "opis/closure": "^3.6", - "php": "^7.3|^8.0", - "ramsey/uuid": "^4.2.2", - "symfony/process": "^5.4" + "illuminate/collections": "^11.0", + "illuminate/console": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/database": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/pipeline": "^11.0", + "illuminate/support": "^11.0", + "laravel/serializable-closure": "^1.3|^2.0", + "php": "^8.2", + "ramsey/uuid": "^4.7", + "symfony/process": "^7.0.3" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.198.1).", + "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.322.9).", + "ext-filter": "Required to use the SQS queue worker.", + "ext-mbstring": "Required to use the database failed job providers.", "ext-pcntl": "Required to use all features of the queue worker.", + "ext-pdo": "Required to use the database queue worker.", "ext-posix": "Required to use all features of the queue worker.", - "illuminate/redis": "Required to use the Redis queue driver (^8.0).", - "pda/pheanstalk": "Required to use the Beanstalk queue driver (^4.0)." + "illuminate/redis": "Required to use the Redis queue driver (^11.0).", + "pda/pheanstalk": "Required to use the Beanstalk queue driver (^5.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2201,39 +2440,40 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-07-21T19:36:12+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/session", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/session.git", - "reference": "9c9988d7229d888c098eebbbb9fcb8c68580411c" + "reference": "00a36b354c12a414236218c1ad193c445b36a191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/session/zipball/9c9988d7229d888c098eebbbb9fcb8c68580411c", - "reference": "9c9988d7229d888c098eebbbb9fcb8c68580411c", + "url": "https://api.github.com/repos/illuminate/session/zipball/00a36b354c12a414236218c1ad193c445b36a191", + "reference": "00a36b354c12a414236218c1ad193c445b36a191", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/filesystem": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0", - "symfony/finder": "^5.4", - "symfony/http-foundation": "^5.4" + "ext-ctype": "*", + "ext-session": "*", + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.0.3" }, "suggest": { - "illuminate/console": "Required to use the session:table command (^8.0)." + "illuminate/console": "Required to use the session:table command (^11.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2257,52 +2497,61 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-13T18:28:06+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/support", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "1c79242468d3bbd9a0f7477df34f9647dde2a09b" + "reference": "915efb197e615dc8adf52fa96d02b9035ff9ce6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/1c79242468d3bbd9a0f7477df34f9647dde2a09b", - "reference": "1c79242468d3bbd9a0f7477df34f9647dde2a09b", + "url": "https://api.github.com/repos/illuminate/support/zipball/915efb197e615dc8adf52fa96d02b9035ff9ce6f", + "reference": "915efb197e615dc8adf52fa96d02b9035ff9ce6f", "shasum": "" }, "require": { - "doctrine/inflector": "^1.4|^2.0", - "ext-json": "*", + "doctrine/inflector": "^2.0", + "ext-ctype": "*", + "ext-filter": "*", "ext-mbstring": "*", - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "nesbot/carbon": "^2.53.1", - "php": "^7.3|^8.0", - "voku/portable-ascii": "^1.6.1" + "illuminate/collections": "^11.0", + "illuminate/conditionable": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "nesbot/carbon": "^2.72.6|^3.8.4", + "php": "^8.2", + "voku/portable-ascii": "^2.0.2" }, "conflict": { "tightenco/collect": "<5.5.33" }, + "replace": { + "spatie/once": "*" + }, "suggest": { - "illuminate/filesystem": "Required to use the composer class (^8.0).", - "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0.2).", - "ramsey/uuid": "Required to use Str::uuid() (^4.2.2).", - "symfony/process": "Required to use the composer class (^5.4).", - "symfony/var-dumper": "Required to use the dd function (^5.4).", - "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." + "illuminate/filesystem": "Required to use the Composer class (^11.0).", + "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.6).", + "league/uri": "Required to use the Uri class (^7.5.1).", + "ramsey/uuid": "Required to use Str::uuid() (^4.7).", + "symfony/process": "Required to use the Composer class (^7.0).", + "symfony/uid": "Required to use Str::ulid() (^7.0).", + "symfony/var-dumper": "Required to use the dd function (^7.0).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { "files": [ + "functions.php", "helpers.php" ], "psr-4": { @@ -2325,41 +2574,42 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-09-21T21:30:03+00:00" + "time": "2025-04-25T08:31:51+00:00" }, { "name": "illuminate/testing", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/testing.git", - "reference": "1c9ec9902df3b7a38b983bbf2242ce3c088de400" + "reference": "a9b9b829f597e5d085ff359b7e367a82bc71276c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/testing/zipball/1c9ec9902df3b7a38b983bbf2242ce3c088de400", - "reference": "1c9ec9902df3b7a38b983bbf2242ce3c088de400", + "url": "https://api.github.com/repos/illuminate/testing/zipball/a9b9b829f597e5d085ff359b7e367a82bc71276c", + "reference": "a9b9b829f597e5d085ff359b7e367a82bc71276c", "shasum": "" }, "require": { - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "ext-mbstring": "*", + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "suggest": { - "brianium/paratest": "Required to run tests in parallel (^6.0).", - "illuminate/console": "Required to assert console commands (^8.0).", - "illuminate/database": "Required to assert databases (^8.0).", - "illuminate/http": "Required to assert responses (^8.0).", - "mockery/mockery": "Required to use mocking (^1.4.4).", - "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8)." + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "illuminate/console": "Required to assert console commands (^11.0).", + "illuminate/database": "Required to assert databases (^11.0).", + "illuminate/http": "Required to assert responses (^11.0).", + "mockery/mockery": "Required to use mocking (^1.6).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2383,35 +2633,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-05-24T14:00:18+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/translation", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/translation.git", - "reference": "e119d1e55351bd846579c333dd24f9a042b724b2" + "reference": "de64584470b1d4bfc30f2c291585b873ce844ecf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/translation/zipball/e119d1e55351bd846579c333dd24f9a042b724b2", - "reference": "e119d1e55351bd846579c333dd24f9a042b724b2", + "url": "https://api.github.com/repos/illuminate/translation/zipball/de64584470b1d4bfc30f2c291585b873ce844ecf", + "reference": "de64584470b1d4bfc30f2c291585b873ce844ecf", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/filesystem": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "illuminate/collections": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2435,43 +2684,44 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-05-02T13:55:33+00:00" + "time": "2025-02-14T15:47:05+00:00" }, { "name": "illuminate/validation", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/validation.git", - "reference": "bb104f15545a55664755f58a278c7013f835918a" + "reference": "fd6a85a4c5cad1a6f84b94aebaec71ea996307b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/validation/zipball/bb104f15545a55664755f58a278c7013f835918a", - "reference": "bb104f15545a55664755f58a278c7013f835918a", + "url": "https://api.github.com/repos/illuminate/validation/zipball/fd6a85a4c5cad1a6f84b94aebaec71ea996307b0", + "reference": "fd6a85a4c5cad1a6f84b94aebaec71ea996307b0", "shasum": "" }, "require": { - "egulias/email-validator": "^2.1.10", - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "illuminate/translation": "^8.0", - "php": "^7.3|^8.0", - "symfony/http-foundation": "^5.4", - "symfony/mime": "^5.4" + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "egulias/email-validator": "^3.2.5|^4.0", + "ext-filter": "*", + "ext-mbstring": "*", + "illuminate/collections": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "illuminate/translation": "^11.0", + "php": "^8.2", + "symfony/http-foundation": "^7.0", + "symfony/mime": "^7.0" }, "suggest": { - "ext-bcmath": "Required to use the multiple_of validation rule.", - "illuminate/database": "Required to use the database presence verifier (^8.0)." + "illuminate/database": "Required to use the database presence verifier (^11.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2495,37 +2745,37 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-05-30T13:21:10+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "illuminate/view", - "version": "v8.83.27", + "version": "v11.44.7", "source": { "type": "git", "url": "https://github.com/illuminate/view.git", - "reference": "5e73eef48d9242532f81fadc14c816a01bfb1388" + "reference": "9da5543dccb4e406f98016bac8678c97b7dc6915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/view/zipball/5e73eef48d9242532f81fadc14c816a01bfb1388", - "reference": "5e73eef48d9242532f81fadc14c816a01bfb1388", + "url": "https://api.github.com/repos/illuminate/view/zipball/9da5543dccb4e406f98016bac8678c97b7dc6915", + "reference": "9da5543dccb4e406f98016bac8678c97b7dc6915", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/collections": "^8.0", - "illuminate/container": "^8.0", - "illuminate/contracts": "^8.0", - "illuminate/events": "^8.0", - "illuminate/filesystem": "^8.0", - "illuminate/macroable": "^8.0", - "illuminate/support": "^8.0", - "php": "^7.3|^8.0" + "ext-tokenizer": "*", + "illuminate/collections": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/events": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/support": "^11.0", + "php": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2549,34 +2799,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-04-14T13:47:10+00:00" + "time": "2025-03-24T11:54:20+00:00" }, { "name": "jobcloud/php-kafka-lib", - "version": "v1.7.1", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/jobcloud/php-kafka-lib.git", - "reference": "2bb7f9c7b771786f37e6f38a168423f480894292" + "reference": "d66de3f984786cf48cca2afbbae4744281747277" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jobcloud/php-kafka-lib/zipball/2bb7f9c7b771786f37e6f38a168423f480894292", - "reference": "2bb7f9c7b771786f37e6f38a168423f480894292", + "url": "https://api.github.com/repos/jobcloud/php-kafka-lib/zipball/d66de3f984786cf48cca2afbbae4744281747277", + "reference": "d66de3f984786cf48cca2afbbae4744281747277", "shasum": "" }, "require": { "ext-json": "*", "ext-rdkafka": "^4.0|^5.0|^6.0", - "php": "^7.3|^8.0" + "php": "^8.0" }, "require-dev": { "flix-tech/avro-serde-php": "^1.4", - "infection/infection": "^0.22", + "infection/infection": "^0.26", "johnkary/phpunit-speedtrap": "^3.1", "kwn/php-rdkafka-stubs": "^2.0.0", "php-mock/php-mock-phpunit": "^2.6", - "phpstan/phpstan": "^0.12", + "phpstan/phpstan": "^1.8", "phpunit/phpunit": "^9.4", "rregeer/phpunit-coverage-check": "^0.3.1", "squizlabs/php_codesniffer": "^3.5.4" @@ -2614,74 +2864,76 @@ ], "support": { "issues": "https://github.com/jobcloud/php-kafka-lib/issues", - "source": "https://github.com/jobcloud/php-kafka-lib/tree/v1.7.1" + "source": "https://github.com/jobcloud/php-kafka-lib/tree/v2.0.0" }, - "time": "2022-12-07T08:12:08+00:00" + "time": "2022-12-30T09:21:59+00:00" }, { "name": "laravel/lumen-framework", - "version": "v8.3.4", + "version": "v11.2.0", "source": { "type": "git", "url": "https://github.com/laravel/lumen-framework.git", - "reference": "733d1199d3344be337743f11df31b4048ec7fd1c" + "reference": "4eb662c94101689c42e48dd395d8f340baefbcac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/733d1199d3344be337743f11df31b4048ec7fd1c", - "reference": "733d1199d3344be337743f11df31b4048ec7fd1c", + "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/4eb662c94101689c42e48dd395d8f340baefbcac", + "reference": "4eb662c94101689c42e48dd395d8f340baefbcac", "shasum": "" }, "require": { - "dragonmantank/cron-expression": "^3.0.2", - "illuminate/auth": "^8.65", - "illuminate/broadcasting": "^8.65", - "illuminate/bus": "^8.65", - "illuminate/cache": "^8.65", - "illuminate/collections": "^8.65", - "illuminate/config": "^8.65", - "illuminate/console": "^8.65", - "illuminate/container": "^8.65", - "illuminate/contracts": "^8.65", - "illuminate/database": "^8.65", - "illuminate/encryption": "^8.65", - "illuminate/events": "^8.65", - "illuminate/filesystem": "^8.65", - "illuminate/hashing": "^8.65", - "illuminate/http": "^8.65", - "illuminate/log": "^8.65", - "illuminate/macroable": "^8.65", - "illuminate/pagination": "^8.65", - "illuminate/pipeline": "^8.65", - "illuminate/queue": "^8.65", - "illuminate/support": "^8.65", - "illuminate/testing": "^8.65", - "illuminate/translation": "^8.65", - "illuminate/validation": "^8.65", - "illuminate/view": "^8.65", + "composer-runtime-api": "^2.2", + "dragonmantank/cron-expression": "^3.1", + "illuminate/auth": "^11.0", + "illuminate/broadcasting": "^11.0", + "illuminate/bus": "^11.0", + "illuminate/cache": "^11.0", + "illuminate/collections": "^11.0", + "illuminate/config": "^11.0", + "illuminate/console": "^11.0", + "illuminate/container": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/database": "^11.0", + "illuminate/encryption": "^11.0", + "illuminate/events": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/hashing": "^11.0", + "illuminate/http": "^11.0", + "illuminate/log": "^11.0", + "illuminate/macroable": "^11.0", + "illuminate/pagination": "^11.0", + "illuminate/pipeline": "^11.0", + "illuminate/queue": "^11.0", + "illuminate/support": "^11.0", + "illuminate/testing": "^11.0", + "illuminate/translation": "^11.0", + "illuminate/validation": "^11.0", + "illuminate/view": "^11.0", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", "nikic/fast-route": "^1.3", - "php": "^7.3|^8.0", - "symfony/console": "^5.4", - "symfony/error-handler": "^5.4", - "symfony/http-foundation": "^5.4", - "symfony/http-kernel": "^5.4", - "symfony/mime": "^5.4", - "symfony/var-dumper": "^5.4", - "vlucas/phpdotenv": "^5.2" + "php": "^8.2", + "symfony/console": "^7.0", + "symfony/error-handler": "^7.0", + "symfony/http-foundation": "^7.0", + "symfony/http-kernel": "^7.0", + "symfony/mime": "^7.0", + "symfony/var-dumper": "^7.0", + "vlucas/phpdotenv": "^5.4.1" }, "require-dev": { - "mockery/mockery": "^1.4.4", - "phpunit/phpunit": "^8.5.19|^9.5.8" + "mockery/mockery": "^1.6.10", + "phpunit/phpunit": "^10.5.35" }, "suggest": { - "laravel/tinker": "Required to use the tinker console command (^2.0).", + "laravel/tinker": "Required to use the tinker console command (^2.7).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { @@ -2713,36 +2965,95 @@ "issues": "https://github.com/laravel/lumen-framework/issues", "source": "https://github.com/laravel/lumen-framework" }, - "time": "2021-12-22T10:11:35+00:00" + "time": "2024-11-26T15:27:28+00:00" }, { - "name": "laravel/serializable-closure", - "version": "v1.3.5", + "name": "laravel/prompts", + "version": "v0.3.5", "source": { "type": "git", - "url": "https://github.com/laravel/serializable-closure.git", - "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c" + "url": "https://github.com/laravel/prompts.git", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", - "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", + "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.61|^3.0", - "pestphp/pest": "^1.21.3", - "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.5" + }, + "time": "2025-02-11T13:34:40+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" } }, "autoload": { @@ -2774,46 +3085,47 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-09-23T13:33:08+00:00" + "time": "2025-03-19T13:51:03+00:00" }, { "name": "monolog/monolog", - "version": "2.9.3", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215" + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/a30bfe2e142720dfa990d0a7e573997f5d884215", - "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + "psr/log-implementation": "3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "aws/aws-sdk-php": "^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", - "guzzlehttp/guzzle": "^7.4", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.38 || ^9.6.19", - "predis/predis": "^1.1 || ^2.0", - "rollbar/rollbar": "^1.3 || ^2 || ^3", - "ruflin/elastica": "^7", - "swiftmailer/swiftmailer": "^5.3|^6.0", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -2836,7 +3148,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -2864,7 +3176,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.9.3" + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, "funding": [ { @@ -2876,56 +3188,51 @@ "type": "tidelift" } ], - "time": "2024-04-12T20:52:51+00:00" + "time": "2025-03-24T10:02:05+00:00" }, { "name": "nesbot/carbon", - "version": "2.72.5", + "version": "3.9.0", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/afd46589c216118ecd48ff2b95d77596af1e57ed", - "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d", + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "*", + "carbonphp/carbon-doctrine-types": "<100.0", "ext-json": "*", - "php": "^7.1.8 || ^8.0", + "php": "^8.1", "psr/clock": "^1.0", + "symfony/clock": "^6.3 || ^7.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", - "doctrine/orm": "^2.7 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.0", - "kylekatarnls/multi-tester": "^2.0", - "ondrejmirtes/better-reflection": "*", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.99 || ^1.7.14", - "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", - "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", - "squizlabs/php_codesniffer": "^3.4" + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.57.2", + "kylekatarnls/multi-tester": "^2.5.3", + "ondrejmirtes/better-reflection": "^6.25.0.4", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.11.2", + "phpunit/phpunit": "^10.5.20", + "squizlabs/php_codesniffer": "^3.9.0" }, "bin": [ "bin/carbon" ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev", - "dev-2.x": "2.x-dev" - }, "laravel": { "providers": [ "Carbon\\Laravel\\ServiceProvider" @@ -2935,6 +3242,10 @@ "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" } }, "autoload": { @@ -2966,8 +3277,8 @@ ], "support": { "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { @@ -2983,7 +3294,7 @@ "type": "tidelift" } ], - "time": "2024-06-03T19:18:41+00:00" + "time": "2025-03-27T12:57:33+00:00" }, { "name": "nikic/fast-route", @@ -3036,38 +3347,51 @@ "time": "2018-02-13T20:26:39+00:00" }, { - "name": "opis/closure", - "version": "3.6.3", + "name": "nunomaduro/termwind", + "version": "v2.3.0", "source": { "type": "git", - "url": "https://github.com/opis/closure.git", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad" + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0" + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.1.8" }, "require-dev": { - "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "illuminate/console": "^11.33.2", + "laravel/pint": "^1.18.2", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.11", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.8", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, "branch-alias": { - "dev-master": "3.6.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { "files": [ - "functions.php" + "src/Functions.php" ], "psr-4": { - "Opis\\Closure\\": "src/" + "Termwind\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3076,29 +3400,38 @@ ], "authors": [ { - "name": "Marius Sarca", - "email": "marius.sarca@gmail.com" - }, - { - "name": "Sorin Sarca", - "email": "sarca_sorin@hotmail.com" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", - "homepage": "https://opis.io/closure", + "description": "Its like Tailwind CSS, but for the console.", "keywords": [ - "anonymous functions", - "closure", - "function", - "serializable", - "serialization", - "serialize" + "cli", + "console", + "css", + "package", + "php", + "style" ], "support": { - "issues": "https://github.com/opis/closure/issues", - "source": "https://github.com/opis/closure/tree/3.6.3" + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" }, - "time": "2022-01-27T09:35:39+00:00" + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2024-11-21T10:39:51+00:00" }, { "name": "phpoption/phpoption", @@ -3225,22 +3558,27 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "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/" @@ -3267,9 +3605,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -3483,16 +3821,16 @@ }, { "name": "psr/log", - "version": "2.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -3501,7 +3839,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { @@ -3527,31 +3865,31 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/2.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:41:46+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "psr/simple-cache", - "version": "1.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -3566,7 +3904,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -3578,9 +3916,9 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2021-10-29T13:26:27+00:00" }, { "name": "ralouphie/getallheaders", @@ -3628,43 +3966,39 @@ }, { "name": "ramsey/collection", - "version": "1.3.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "symfony/polyfill-php81": "^1.23" + "php": "^8.1" }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.28.3", - "fakerphp/faker": "^1.21", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", - "mockery/mockery": "^1.5", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-rc1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18.4", - "ramsey/coding-standard": "^2.0.3", - "ramsey/conventional-commits": "^1.3", - "vimeo/psalm": "^5.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" }, "type": "library", "extra": { @@ -3702,19 +4036,9 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.3.0" + "source": "https://github.com/ramsey/collection/tree/2.1.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" - } - ], - "time": "2022-12-27T19:12:24+00:00" + "time": "2025-03-22T05:38:12+00:00" }, { "name": "ramsey/uuid", @@ -3808,54 +4132,122 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "symfony/clock", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "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": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.2.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/console", - "version": "v5.4.44", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83" + "reference": "e51498ea18570c062e7df29d05a7003585b19b88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5b5a0aa66e3296e303e22490f90f521551835a83", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83", + "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", + "reference": "e51498ea18570c062e7df29d05a7003585b19b88", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3889,7 +4281,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.44" + "source": "https://github.com/symfony/console/tree/v7.2.5" }, "funding": [ { @@ -3905,33 +4297,33 @@ "type": "tidelift" } ], - "time": "2024-09-20T07:56:40+00:00" + "time": "2025-03-12T08:11:12+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -3956,7 +4348,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3972,31 +4364,35 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/error-handler", - "version": "v5.4.42", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "db15ba0fd50890156ed40087ccedc7851a1f5b76" + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/db15ba0fd50890156ed40087ccedc7851a1f5b76", - "reference": "db15ba0fd50890156ed40087ccedc7851a1f5b76", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4027,7 +4423,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.4.42" + "source": "https://github.com/symfony/error-handler/tree/v7.2.5" }, "funding": [ { @@ -4043,28 +4439,29 @@ "type": "tidelift" } ], - "time": "2024-07-23T12:34:05+00:00" + "time": "2025-03-03T07:12:39+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.0.19", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", - "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/event-dispatcher-contracts": "^2|^3" + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -4072,17 +4469,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^5.4|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4110,7 +4503,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.19" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -4126,37 +4519,34 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -4189,7 +4579,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -4205,26 +4595,27 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/finder", - "version": "v5.4.43", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ae25a9145a900764158d439653d5630191155ca0" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ae25a9145a900764158d439653d5630191155ca0", - "reference": "ae25a9145a900764158d439653d5630191155ca0", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4252,7 +4643,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.43" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -4268,39 +4659,41 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:03:51+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.44", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ae0d217e5932aa0b70ddb4cf7822cc76d48aee53" + "reference": "371272aeb6286f8135e028ca535f8e4d6f114126" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ae0d217e5932aa0b70ddb4cf7822cc76d48aee53", - "reference": "ae0d217e5932aa0b70ddb4cf7822cc76d48aee53", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126", + "reference": "371272aeb6286f8135e028ca535f8e4d6f114126", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-php83": "^1.27" }, - "require-dev": { - "predis/predis": "^1.0|^2.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, - "suggest": { - "symfony/mime": "To use the file extension guesser" + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4328,7 +4721,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.44" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.5" }, "funding": [ { @@ -4344,76 +4737,77 @@ "type": "tidelift" } ], - "time": "2024-09-15T07:55:06+00:00" + "time": "2025-03-25T15:54:33+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.44", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "788dcf72d9af7432a886aa3b0c5904d68087ba13" + "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/788dcf72d9af7432a886aa3b0c5904d68087ba13", - "reference": "788dcf72d9af7432a886aa3b0c5904d68087ba13", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/log": "^1|^2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^5.0|^6.0", - "symfony/http-foundation": "^5.4.21|^6.2.7", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/console": "<4.4", - "symfony/dependency-injection": "<5.3", - "symfony/doctrine-bridge": "<5.0", - "symfony/form": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.13" + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "symfony/var-dumper": "^4.4.31|^5.4", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" }, "type": "library", "autoload": { @@ -4441,7 +4835,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.44" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.5" }, "funding": [ { @@ -4457,44 +4851,43 @@ "type": "tidelift" } ], - "time": "2024-09-21T05:47:58+00:00" + "time": "2025-03-28T13:32:50+00:00" }, { "name": "symfony/mime", - "version": "v5.4.43", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "a02711d6ce461edada8c0f8641aa536709b99b47" + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/a02711d6ce461edada8c0f8641aa536709b99b47", - "reference": "a02711d6ce461edada8c0f8641aa536709b99b47", + "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<4.4", - "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/process": "^5.4|^6.4", - "symfony/property-access": "^4.4|^5.1|^6.0", - "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3" + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", "autoload": { @@ -4526,7 +4919,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.4.43" + "source": "https://github.com/symfony/mime/tree/v7.2.4" }, "funding": [ { @@ -4542,7 +4935,7 @@ "type": "tidelift" } ], - "time": "2024-08-13T10:38:38+00:00" + "time": "2025-02-19T08:51:20+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4570,8 +4963,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4646,8 +5039,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4725,8 +5118,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4789,110 +5182,26 @@ "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.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-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { "php": ">=7.2" }, - "provide": { - "ext-mbstring": "*" - }, "suggest": { - "ext-mbstring": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4900,8 +5209,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4917,17 +5229,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "intl", + "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -4946,27 +5259,33 @@ "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php73", + "name": "symfony/polyfill-mbstring", "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { "php": ">=7.2" }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4974,11 +5293,8 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4994,16 +5310,17 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -5041,8 +5358,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -5102,17 +5419,17 @@ "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php81", + "name": "symfony/polyfill-php83", "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { @@ -5121,8 +5438,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -5130,7 +5447,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php83\\": "" }, "classmap": [ "Resources/stubs" @@ -5150,7 +5467,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -5159,7 +5476,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -5179,21 +5496,20 @@ }, { "name": "symfony/process", - "version": "v5.4.44", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096" + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1b9fa82b5c62cd49da8c9e3952dd8531ada65096", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096", + "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -5221,7 +5537,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.44" + "source": "https://github.com/symfony/process/tree/v7.2.5" }, "funding": [ { @@ -5237,47 +5553,47 @@ "type": "tidelift" } ], - "time": "2024-09-17T12:46:43+00:00" + "time": "2025-03-13T12:21:46+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.3", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3", - "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5304,7 +5620,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.3" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -5320,37 +5636,39 @@ "type": "tidelift" } ], - "time": "2023-04-21T15:04:16+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v6.0.19", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5389,7 +5707,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.19" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -5405,55 +5723,55 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "symfony/translation", - "version": "v6.0.19", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5484,7 +5802,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.19" + "source": "https://github.com/symfony/translation/tree/v7.2.4" }, "funding": [ { @@ -5500,42 +5818,42 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2025-02-13T10:27:23+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.0.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { - "php": ">=8.0.2" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5562,7 +5880,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -5578,42 +5896,36 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.4.43", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6be6a6a8af4818564e3726fc65cf936f34743cef" + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6be6a6a8af4818564e3726fc65cf936f34743cef", - "reference": "6be6a6a8af4818564e3726fc65cf936f34743cef", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<4.4" + "symfony/console": "<6.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -5651,7 +5963,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.43" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" }, "funding": [ { @@ -5667,7 +5979,7 @@ "type": "tidelift" } ], - "time": "2024-08-30T16:01:46+00:00" + "time": "2025-01-17T11:39:41+00:00" }, { "name": "vlucas/phpdotenv", @@ -5755,16 +6067,16 @@ }, { "name": "voku/portable-ascii", - "version": "1.6.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a" + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/87337c91b9dfacee02452244ee14ab3c43bc485a", - "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", "shasum": "" }, "require": { @@ -5789,7 +6101,7 @@ "authors": [ { "name": "Lars Moelleken", - "homepage": "http://www.moelleken.org/" + "homepage": "https://www.moelleken.org/" } ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", @@ -5801,7 +6113,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/1.6.1" + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" }, "funding": [ { @@ -5825,7 +6137,7 @@ "type": "tidelift" } ], - "time": "2022-01-24T18:55:24+00:00" + "time": "2024-11-21T01:49:47+00:00" }, { "name": "webmozart/assert", @@ -5887,16 +6199,16 @@ }, { "name": "widmogrod/php-functional", - "version": "6.0.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/widmogrod/php-functional.git", - "reference": "e479913945d885f7d441373ea4926cbba612c1ad" + "reference": "e87398e029b07784cf028ff3363ed61242f58d73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/widmogrod/php-functional/zipball/e479913945d885f7d441373ea4926cbba612c1ad", - "reference": "e479913945d885f7d441373ea4926cbba612c1ad", + "url": "https://api.github.com/repos/widmogrod/php-functional/zipball/e87398e029b07784cf028ff3363ed61242f58d73", + "reference": "e87398e029b07784cf028ff3363ed61242f58d73", "shasum": "" }, "require": { @@ -5951,38 +6263,116 @@ "description": "Functors, Applicative and Monads are fascinating concept. Purpose of this library is to explore them in OOP PHP world.", "support": { "issues": "https://github.com/widmogrod/php-functional/issues", - "source": "https://github.com/widmogrod/php-functional/tree/6.0.1" + "source": "https://github.com/widmogrod/php-functional/tree/6.0.2" }, - "time": "2024-03-25T10:44:45+00:00" + "time": "2024-12-18T18:24:14+00:00" } ], "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "time": "2023-01-05T11:28:13+00:00" + }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -6009,7 +6399,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -6025,20 +6415,154 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -6077,7 +6601,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -6085,20 +6609,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nikic/php-parser", - "version": "v5.3.1", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -6141,9 +6665,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-10-08T18:51:32+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -6263,6 +6787,53 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" + }, + "time": "2025-02-19T13:28:12+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.32", @@ -7694,18 +8265,83 @@ ], "time": "2020-09-28T06:39:44+00:00" }, + { + "name": "slevomat/coding-standard", + "version": "8.17.0", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0", + "reference": "ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.1.0", + "squizlabs/php_codesniffer": "^3.12.1" + }, + "require-dev": { + "phing/phing": "3.0.1", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.11", + "phpstan/phpstan-deprecation-rules": "2.0.1", + "phpstan/phpstan-phpunit": "2.0.6", + "phpstan/phpstan-strict-rules": "2.0.4", + "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.17|12.1.2" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.17.0" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2025-04-10T06:06:16+00:00" + }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.3", + "version": "3.12.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", + "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", "shasum": "" }, "require": { @@ -7770,9 +8406,13 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-09-18T10:38:58+00:00" + "time": "2025-04-13T04:10:18+00:00" }, { "name": "theseer/tokenizer", @@ -7831,8 +8471,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.3|^8.0" + "php": "^8.3" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.6.0" } diff --git a/phpcs.xml b/phpcs.xml index d517f0d..6085b1d 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -25,4 +25,28 @@ database/ storage/ bootstrap/ + src/HelloWorld.php + src/Commands/ + src/Providers/ + src/Libraries/KafkaCallable.php + + + + + + + + + + + + + + + + + + + + diff --git a/phpunit.xml b/phpunit.xml index 08bd676..57ededb 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,7 +19,6 @@ - diff --git a/src/Commands/Command.php b/src/Commands/Command.php index 65672b9..8c038f9 100644 --- a/src/Commands/Command.php +++ b/src/Commands/Command.php @@ -43,6 +43,15 @@ abstract class Command extends BaseCommand public function __construct() { parent::__construct(); + } + + /** + * Setting context required for logger. + * + * @return void + */ + public function setContext(): void + { $this->taskID = uniqid() . '00000'; $context = app(Context::class); $meta = new Metadata(); diff --git a/src/Commands/DtoMakeCommand.php b/src/Commands/DtoMakeCommand.php index abd3ef2..8f2c932 100644 --- a/src/Commands/DtoMakeCommand.php +++ b/src/Commands/DtoMakeCommand.php @@ -50,16 +50,6 @@ class DtoMakeCommand extends GeneratorCommand */ protected $type = 'DTO'; - /** - * Execute the console command. - * - * @return void - */ - public function handle() - { - parent::handle(); - } - /** * Get the stub file for the generator. * diff --git a/src/Commands/stubs/dto.plain.stub b/src/Commands/stubs/dto.plain.stub index 91caba7..56c2d6b 100644 --- a/src/Commands/stubs/dto.plain.stub +++ b/src/Commands/stubs/dto.plain.stub @@ -24,7 +24,7 @@ use Spotlibs\PhpLib\Dtos\TraitDtos; * * @category DataClass * @package Dtos - * @author + * @author Your Name * @license https://mit-license.org/ MIT License * @link https://github.com/ */ @@ -35,7 +35,7 @@ class DummyClass /** * Define which properties as array of Dtos * - * @var array + * @property array $arrayOfObjectMap */ protected array $arrayOfObjectMap = []; @@ -43,7 +43,7 @@ class DummyClass * Define which array keys to be recognized as property in Dtos. * This will override the default property assignment in Dtos that no longer lookup by match property to array key insted match alias to array key * - * @var array + * @property array $aliases */ protected array $aliases = []; } diff --git a/src/Dtos/TraitConvertibleDtos.php b/src/Dtos/TraitConvertibleDtos.php index df5be63..6c8dfee 100644 --- a/src/Dtos/TraitConvertibleDtos.php +++ b/src/Dtos/TraitConvertibleDtos.php @@ -82,7 +82,7 @@ public function toArray(): array * * @return bool|string */ - public function toJson() + public function toJson(): bool|string { $data = $this->toArray(); return json_encode($data); diff --git a/src/Dtos/TraitDtos.php b/src/Dtos/TraitDtos.php index 54fa69c..507c65e 100644 --- a/src/Dtos/TraitDtos.php +++ b/src/Dtos/TraitDtos.php @@ -74,7 +74,7 @@ public function __construct(array $data = []) * * @return void */ - private function convertArray(ReflectionClass &$reflector, string $key, array &$value) + private function convertArray(ReflectionClass &$reflector, string $key, array &$value): void { $prop = $reflector->getProperty($key); $type = $prop->getType()->getName(); @@ -125,6 +125,9 @@ public function recursiveToArray(array $x): array { $result = []; foreach ($x as $key => $value) { + if ($key == 'arrayOfObjectMap' || $key == 'aliases') { + continue; + } if (is_array($value)) { $result[$key] = $this->recursiveToArray($value); } elseif (is_object($value)) { diff --git a/src/Dtos/TypeConverter.php b/src/Dtos/TypeConverter.php index 6963a05..07674ab 100644 --- a/src/Dtos/TypeConverter.php +++ b/src/Dtos/TypeConverter.php @@ -15,10 +15,10 @@ namespace Spotlibs\PhpLib\Dtos; -use ReflectionClass; -use ReflectionProperty; use Carbon\Carbon; use Illuminate\Support\Facades\Log; +use ReflectionClass; +use ReflectionProperty; /** * TypeConverter diff --git a/src/Exceptions/AccessException.php b/src/Exceptions/AccessException.php index b88bb92..e521bb2 100644 --- a/src/Exceptions/AccessException.php +++ b/src/Exceptions/AccessException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class AccessException diff --git a/src/Exceptions/DataNotFoundException.php b/src/Exceptions/DataNotFoundException.php index 35346a9..df2109e 100644 --- a/src/Exceptions/DataNotFoundException.php +++ b/src/Exceptions/DataNotFoundException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class DataNotFoundException diff --git a/src/Exceptions/Handler.php b/src/Exceptions/Handler.php index 4ceae50..7da35ce 100644 --- a/src/Exceptions/Handler.php +++ b/src/Exceptions/Handler.php @@ -16,19 +16,18 @@ namespace Spotlibs\PhpLib\Exceptions; use Exception; -use Laravel\Lumen\Exceptions\Handler as ExceptionHandler; -use Spotlibs\PhpLib\Logs\Log; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\QueryException; -use Illuminate\Validation\ValidationException; use Illuminate\Http\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Illuminate\Validation\ValidationException; +use Laravel\Lumen\Exceptions\Handler as ExceptionHandler; use Spotlibs\PhpLib\Exceptions\DataNotFoundException; +use Spotlibs\PhpLib\Logs\Log; use Spotlibs\PhpLib\Responses\StdResponse; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; -use TypeError; /** * Class Handler @@ -46,7 +45,7 @@ class Handler extends ExceptionHandler * * @var array */ - protected $dontReport = [ + protected array $dontReport = [ AuthorizationException::class, HttpException::class, ValidationException::class @@ -63,7 +62,7 @@ class Handler extends ExceptionHandler * * @throws \Exception */ - public function report(Throwable $exception) + public function report(Throwable $exception): void { if ((!$exception instanceof ExceptionInterface && !$exception instanceof NotFoundHttpException && !$exception instanceof ValidationException) || $exception instanceof RuntimeException) { Log::runtime()->error( @@ -86,7 +85,7 @@ public function report(Throwable $exception) * * @throws \Throwable */ - public function render($request, Throwable $exception): Response + public function render(mixed $request, Throwable $exception): Response { if ($exception instanceof NotFoundHttpException || $exception instanceof HttpException) { $exception = new UnsupportedException("Route --" . $request->getPathInfo() . "-- not found in " . ENV('APP_NAME') . "!"); diff --git a/src/Exceptions/HeaderException.php b/src/Exceptions/HeaderException.php index b8f91b0..689b9e5 100644 --- a/src/Exceptions/HeaderException.php +++ b/src/Exceptions/HeaderException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class HeaderException diff --git a/src/Exceptions/InvalidRuleException.php b/src/Exceptions/InvalidRuleException.php index f4fa567..98bf660 100644 --- a/src/Exceptions/InvalidRuleException.php +++ b/src/Exceptions/InvalidRuleException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class InvalidRuleException diff --git a/src/Exceptions/ParameterException.php b/src/Exceptions/ParameterException.php index 500992c..9c0a05c 100644 --- a/src/Exceptions/ParameterException.php +++ b/src/Exceptions/ParameterException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class ParameterException diff --git a/src/Exceptions/RuntimeException.php b/src/Exceptions/RuntimeException.php index 17cd898..7427994 100644 --- a/src/Exceptions/RuntimeException.php +++ b/src/Exceptions/RuntimeException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class RuntimeException diff --git a/src/Exceptions/StdException.php b/src/Exceptions/StdException.php index e8bf7e6..a98a4fc 100644 --- a/src/Exceptions/StdException.php +++ b/src/Exceptions/StdException.php @@ -16,15 +16,15 @@ namespace Spotlibs\PhpLib\Exceptions; use Spotlibs\PhpLib\Exceptions\AccessException; -use Spotlibs\PhpLib\Exceptions\ParameterException; use Spotlibs\PhpLib\Exceptions\DataNotFoundException; -use Spotlibs\PhpLib\Exceptions\InvalidRuleException; -use Spotlibs\PhpLib\Exceptions\ThirdPartyServiceException; -use Spotlibs\PhpLib\Exceptions\WaitingException; -use Spotlibs\PhpLib\Exceptions\UnsupportedException; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; use Spotlibs\PhpLib\Exceptions\HeaderException; +use Spotlibs\PhpLib\Exceptions\InvalidRuleException; +use Spotlibs\PhpLib\Exceptions\ParameterException; use Spotlibs\PhpLib\Exceptions\RuntimeException; +use Spotlibs\PhpLib\Exceptions\ThirdPartyServiceException; +use Spotlibs\PhpLib\Exceptions\UnsupportedException; +use Spotlibs\PhpLib\Exceptions\WaitingException; /** * Class StdException diff --git a/src/Exceptions/ThirdPartyServiceException.php b/src/Exceptions/ThirdPartyServiceException.php index 5afa114..887ccab 100644 --- a/src/Exceptions/ThirdPartyServiceException.php +++ b/src/Exceptions/ThirdPartyServiceException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class ThirdPartyServiceException diff --git a/src/Exceptions/UnsupportedException.php b/src/Exceptions/UnsupportedException.php index dc17f6f..db0cef0 100644 --- a/src/Exceptions/UnsupportedException.php +++ b/src/Exceptions/UnsupportedException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class UnsupportedException diff --git a/src/Exceptions/WaitingException.php b/src/Exceptions/WaitingException.php index 6a91725..24f3dbe 100644 --- a/src/Exceptions/WaitingException.php +++ b/src/Exceptions/WaitingException.php @@ -17,8 +17,8 @@ use Exception; use Spotlibs\PhpLib\Exceptions\ExceptionInterface; -use Spotlibs\PhpLib\Exceptions\TraitException; use Spotlibs\PhpLib\Exceptions\StdException; +use Spotlibs\PhpLib\Exceptions\TraitException; /** * Class WaitingException diff --git a/src/Facades/Queue.php b/src/Facades/Queue.php index e989a95..6ca0621 100644 --- a/src/Facades/Queue.php +++ b/src/Facades/Queue.php @@ -15,7 +15,6 @@ namespace Spotlibs\PhpLib\Facades; -use DateTime; use Illuminate\Support\Facades\Queue as BaseQueue; use Spotlibs\PhpLib\Services\Context; use Spotlibs\PhpLib\Services\Metadata; diff --git a/src/Libraries/Client.php b/src/Libraries/Client.php index 955e8ab..23b6b5a 100644 --- a/src/Libraries/Client.php +++ b/src/Libraries/Client.php @@ -18,6 +18,7 @@ use GuzzleHttp\Client as BaseClient; use GuzzleHttp\Psr7\Request; use Psr\Http\Message\ResponseInterface; +use Spotlibs\PhpLib\Exceptions\StdException; /** * ClientTimeoutUnit @@ -32,18 +33,6 @@ */ class Client extends BaseClient { - /** - * Timeout in seconds, default is 10 seconds - * - * @var float $timeout - */ - public float $timeout = 10; - /** - * Set to true to enable SSL certificate verification and use the default CA bundle provided by operating system - * - * @var bool $verify - */ - public bool $verify = false; /** * Request body, set according to the request * @@ -79,32 +68,6 @@ public function __construct() parent::__construct(); } - /** - * Set the timeout for Http Client - * - * @param float $timeout number of desired timeout - * - * @return self - */ - public function setTimeout(float $timeout): self - { - $this->timeout = $timeout; - return $this; - } - - /** - * Set verify - * - * @param bool $verify number of desired timeout - * - * @return self - */ - public function setVerify(bool $verify): self - { - $this->verify = $verify; - return $this; - } - /** * Set request headers in associative array * @@ -132,19 +95,37 @@ public function injectResponseHeader(array $headers): self } /** - * Set the timeout for Http Client + * Execute the HTTP request through GuzzleHttp Client * * @param Request $request HTTP Request instance + * @param array $options Guzzle HTTP client options. See more at https://docs.guzzlephp.org/en/stable/request-options.html * * @return ResponseInterface */ - public function call(Request $request): ResponseInterface + public function call(Request $request, array $options = []): ResponseInterface { - $options = ['timeout' => $this->timeout, 'verify' => $this->verify]; + if (!isset($options['timeout'])) { + $options['timeout'] = 10; + } + if (!isset($options['verify'])) { + $options['verify'] = false; + } foreach ($this->requestHeaders as $key => $header) { $request = $request->withHeader($key, $header); } $response = $this->send($request, $options); + if ($response->getStatusCode() === 200) { + $decoded = json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR); + if (isset($decoded['responseCode']) && $decoded['responseCode'] <> '00') { + throw StdException::create( + $decoded['responseCode'], + $decoded['responseDesc'], + $decoded['responseData'] ?? null, + $decoded['validationErrors'] ?? [], + ); + } + $response->getBody()->rewind(); + } foreach ($this->responseHeaders as $key => $header) { $response = $response->withHeader($key, $header); } diff --git a/src/Libraries/ClientExternal.php b/src/Libraries/ClientExternal.php index 278adc0..0959f73 100644 --- a/src/Libraries/ClientExternal.php +++ b/src/Libraries/ClientExternal.php @@ -16,10 +16,13 @@ namespace Spotlibs\PhpLib\Libraries; use GuzzleHttp\Client as BaseClient; -use GuzzleHttp\Psr7\MultipartStream; use GuzzleHttp\Psr7\Request; +use Illuminate\Support\Facades\Redis; use Psr\Http\Message\ResponseInterface; +use Spotlibs\PhpLib\Exceptions\InvalidRuleException; +use Spotlibs\PhpLib\Libraries\MapRoute; use Spotlibs\PhpLib\Logs\Log; +use Throwable; /** * ClientTimeoutUnit @@ -81,32 +84,6 @@ public function __construct() parent::__construct(); } - /** - * Set the timeout for Http Client - * - * @param float $timeout number of desired timeout - * - * @return self - */ - public function setTimeout(float $timeout): self - { - $this->timeout = $timeout; - return $this; - } - - /** - * Set verify - * - * @param bool $verify number of desired timeout - * - * @return self - */ - public function setVerify(bool $verify): self - { - $this->verify = $verify; - return $this; - } - /** * Set request headers in associative array * @@ -134,22 +111,43 @@ public function injectResponseHeader(array $headers): self } /** - * Set the timeout for Http Client + * Execute the HTTP request through GuzzleHttp Client * * @param Request $request HTTP Request instance + * @param array $options Guzzle HTTP client options. See more at https://docs.guzzlephp.org/en/stable/request-options.html * * @return ResponseInterface */ - public function call(Request $request): ResponseInterface + public function call(Request $request, array $options = []): ResponseInterface { $startime = microtime(true); - $options = ['timeout' => $this->timeout, 'verify' => $this->verify]; + $uri = $request->getUri(); + $url = $uri->getScheme() . "://" . $uri->getHost(); + $url .= is_null($uri->getPort()) ? "" : ":" . $uri->getPort(); + $url .= $uri->getPath(); + try { + $maproute = $this->checkMock($url); + if (!empty((array) $maproute) && $maproute->flag) { + $request_temp = new Request( + $request->getMethod(), + $maproute->mock_url, + $request->getHeaders(), + $request->getBody(), + $request->getProtocolVersion() + ); + $request = $request_temp; + $request = $request->withHeader('Host', parse_url($maproute->mock_url, PHP_URL_HOST)); + unset($request_temp); + } + } catch (Throwable $th) { + //do nothing + } + if (!isset($options['timeout'])) { + $options['timeout'] = 60; + } foreach ($this->requestHeaders as $key => $header) { $request = $request->withHeader($key, $header); } - if (!$request->hasHeader('Content-Type')) { - $request = $request->withHeader('Content-Type', 'application/json'); - } $response = $this->send($request, $options); foreach ($this->responseHeaders as $key => $header) { $response = $response->withHeader($key, $header); @@ -157,16 +155,19 @@ public function call(Request $request): ResponseInterface $elapsed = microtime(true) - $startime; if (env('APP_DEBUG', false)) { $request->getBody()->rewind(); - if (strlen($reqbody = $request->getBody()->getContents()) > 5000) { + $reqbody = $request->getBody()->getContents(); + $respbody = $response->getBody()->getContents(); + if (strlen($reqbody) > 5000) { $reqbody = "more than 5000 characters"; } - if (strlen($respbody = $response->getBody()->getContents()) > 5000) { + if (strlen($respbody) > 5000) { $respbody = "more than 5000 characters"; } $logData = [ 'host' => $request->getUri()->getHost(), 'url' => $request->getUri()->getPath(), 'request' => [ + 'method' => $request->getMethod(), 'headers' => $request->getHeaders(), 'body' => json_decode($reqbody, true) ], @@ -182,4 +183,21 @@ public function call(Request $request): ResponseInterface } return $response; } + + /** + * Check if url shall mock + * + * @param string $url full url of the request + * + * @return array + */ + private function checkMock(string $url): MapRoute + { + if (env('APP_ENV') == 'production') { + throw new InvalidRuleException('Cannot use mock in production environment'); + } + $maproute = Redis::get('eksternal_mock_url_mapping:' . $url); + $maproute = json_decode($maproute, true, 512, JSON_THROW_ON_ERROR); + return new MapRoute($maproute); + } } diff --git a/src/Libraries/Kafka.php b/src/Libraries/Kafka.php deleted file mode 100644 index 2a60bc6..0000000 --- a/src/Libraries/Kafka.php +++ /dev/null @@ -1,251 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.0.4 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries; - -use GuzzleHttp\Client; -use Jobcloud\Kafka\Message\KafkaAvroSchema; -use Jobcloud\Kafka\Message\KafkaAvroSchemaInterface; -use Jobcloud\Kafka\Message\Registry\AvroSchemaRegistry; -use FlixTech\AvroSerializer\Objects\RecordSerializer; -use FlixTech\SchemaRegistryApi\Registry\CachedRegistry; -use FlixTech\SchemaRegistryApi\Registry\BlockingRegistry; -use FlixTech\SchemaRegistryApi\Registry\PromisingRegistry; -use FlixTech\SchemaRegistryApi\Registry\Cache\AvroObjectCacheAdapter; -use Jobcloud\Kafka\Producer\KafkaProducerBuilder; -use Jobcloud\Kafka\Message\Encoder\AvroEncoder; -use Jobcloud\Kafka\Message\Encoder\JsonEncoder; -use Jobcloud\Kafka\Consumer\KafkaConsumerBuilder; -use Jobcloud\Kafka\Consumer\KafkaConsumerInterface; -use Jobcloud\Kafka\Message\Decoder\AvroDecoder; -use Jobcloud\Kafka\Message\Decoder\JsonDecoder; -use Jobcloud\Kafka\Producer\KafkaProducerInterface; - -/** - * Kafka - * - * @category StandardLibrary - * @package Libraries - * @author Hendri Nursyahbani - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class Kafka -{ - public const SCHEMALESS = 1; // Tidak berskema - public const SCHEMALESS_WITH_SERDE = 2; // Tidak berskema tapi memiliki mekanisme encode dan decode - public const SCHEMAFULL_WITH_SERDE = 3; // Berskema sekaligus memiliki mekanisme encode dan decode - - /** - * Publish new message to Kafka topic - * - * @param string $topic_name kafka topic name - * @param int $schematype kafka schema type - * @param string|null $definitionSchemaBody schema body - * @param string|null $definitionSchemaKey schema key - * - * @return \Jobcloud\Kafka\Producer\KafkaProducerInterface - */ - public function publishOn(string $topic_name, int $schematype, string $definitionSchemaBody = null, string $definitionSchemaKey = null): KafkaProducerInterface - { - if (env('KAFKA_SCHEME_REGISTRY_URL') === null) { - throw new \Exception('Env KAFKA_SCHEME_REGISTRY_URL not provide yet'); - } - - if (env('KAFKA_USER_PRODUCE') === null) { - throw new \Exception('Env KAFKA_USER_PRODUCE not provide yet'); - } - - if (env('KAFKA_PASS_PRODUCE') === null) { - throw new \Exception('Env KAFKA_PASS_PRODUCE not provide yet'); - } - - if ($schematype === self::SCHEMAFULL_WITH_SERDE) { - $cachedRegistry = new CachedRegistry( - new BlockingRegistry( - new PromisingRegistry( - new Client( - [ - 'base_uri' => env('KAFKA_SCHEME_REGISTRY_URL'), - 'auth' => [env('KAFKA_USER_PRODUCE'), env('KAFKA_PASS_PRODUCE')] - ] - ) - ) - ), - new AvroObjectCacheAdapter() - ); - - $registry = new AvroSchemaRegistry($cachedRegistry); - $recordSerializer = new RecordSerializer( - $cachedRegistry, - [ - RecordSerializer::OPTION_REGISTER_MISSING_SUBJECTS => true, // otomatis di daftarkan subjectny jika belum ada di registry - RecordSerializer::OPTION_REGISTER_MISSING_SCHEMAS => true, // otomatis di daftarkan schemany jika belum ada di registry - ] - ); - - if ($definitionSchemaBody !== null) { - $registry->addBodySchemaMappingForTopic( - $topic_name, - new KafkaAvroSchema($topic_name . '-value', KafkaAvroSchemaInterface::LATEST_VERSION, \AvroSchema::parse($definitionSchemaBody)) - ); - } - - if ($definitionSchemaKey !== null) { - $registry->addKeySchemaMappingForTopic( - $topic_name, - new KafkaAvroSchema($topic_name . '-key', KafkaAvroSchemaInterface::LATEST_VERSION, \AvroSchema::parse($definitionSchemaKey)) - ); - } - - $encoder = new AvroEncoder($registry, $recordSerializer); - } - - if ($schematype === self::SCHEMALESS_WITH_SERDE) { - $encoder = new JsonEncoder(); - } - - $producerBuilder = KafkaProducerBuilder::create() - ->withAdditionalConfig( - [ - 'compression.codec' => 'lz4', - 'sasl.username' => env('KAFKA_USER_PRODUCE'), - 'sasl.password' => env('KAFKA_PASS_PRODUCE'), - 'sasl.mechanism' => 'PLAIN', - 'security.protocol' => 'SASL_SSL', - 'message.timeout.ms' => '8000', - 'socket.timeout.ms' => '8000' - ] - ) - ->withAdditionalBroker(env('KAFKA_BROKERS_URL', '')) - ->withDeliveryReportCallback([KafkaCallable::class, 'deliveryReportCallback']) - ->withLogCallback([KafkaCallable::class, 'logCallback']) - ->withErrorCallback([KafkaCallable::class, 'errorProduceCallback']); - - if ($schematype === self::SCHEMALESS_WITH_SERDE || $schematype === self::SCHEMAFULL_WITH_SERDE) { - $producerBuilder->withEncoder($encoder); - } - - $producer = $producerBuilder->build(); - - return $producer; - } - - /** - * Publish new message to Kafka topic - * - * @param string $topic_name kafka topic name - * @param int $schematype kafka schema type - * @param string|null $congrup_name kafka consumer group name - * - * @return \Jobcloud\Kafka\Consumer\KafkaConsumerInterface - */ - public function consumeOn(string $topic_name, int $schematype, string $congrup_name = null): KafkaConsumerInterface - { - if (env('KAFKA_SCHEME_REGISTRY_URL') === null) { - throw new \Exception('Env KAFKA_SCHEME_REGISTRY_URL not provide yet'); - } - - if (env('KAFKA_USER_CONSUME') === null) { - throw new \Exception('Env KAFKA_USER_CONSUME not provide yet'); - } - - if (env('KAFKA_PASS_CONSUME') === null) { - throw new \Exception('Env KAFKA_PASS_CONSUME not provide yet'); - } - - if ($schematype === self::SCHEMAFULL_WITH_SERDE) { - $cachedRegistry = new CachedRegistry( - new BlockingRegistry( - new PromisingRegistry( - new Client( - [ - 'base_uri' => env('KAFKA_SCHEME_REGISTRY_URL'), - 'auth' => [env('KAFKA_USER_CONSUME'), env('KAFKA_PASS_CONSUME')] - ] - ) - ) - ), - new AvroObjectCacheAdapter() - ); - - $registry = new AvroSchemaRegistry($cachedRegistry); - $recordSerializer = new RecordSerializer($cachedRegistry); - - //if no version is defined, latest version will be used - //if no schema definition is defined, the appropriate version will be fetched form the registry - $registry->addBodySchemaMappingForTopic( - $topic_name, - new KafkaAvroSchema($topic_name . '-value', KafkaAvroSchemaInterface::LATEST_VERSION) - ); - $registry->addKeySchemaMappingForTopic( - $topic_name, - new KafkaAvroSchema($topic_name . '-key', KafkaAvroSchemaInterface::LATEST_VERSION) - ); - - $decoder = new AvroDecoder($registry, $recordSerializer); - } - - if ($schematype === self::SCHEMALESS_WITH_SERDE) { - $decoder = new JsonDecoder(); - } - - - if ($schematype === self::SCHEMALESS_WITH_SERDE || $schematype === self::SCHEMAFULL_WITH_SERDE) { - $consumer = KafkaConsumerBuilder::create()->withAdditionalConfig( - [ - 'client.id' => env('APP_NAME') . '-' . gethostname(), - 'sasl.username' => env('KAFKA_USER_CONSUME'), - 'sasl.password' => env('KAFKA_PASS_CONSUME'), - 'sasl.mechanism' => 'PLAIN', - 'security.protocol' => 'SASL_SSL', - 'socket.timeout.ms' => '10000' - ] - )->withAdditionalBroker(env('KAFKA_BROKERS_URL', '')) - ->withConsumerGroup($topic_name . '_' . (isset($congrup_name) ? $congrup_name : 'congrup')) - ->withAdditionalSubscription($topic_name) - ->withDecoder($decoder) - ->withErrorCallback([KafkaCallable::class, 'errorConsumeCallback']) - ->withRebalanceCallback([KafkaCallable::class, 'rebalanceCallback']) - ->withConsumeCallback([KafkaCallable::class, 'consumeCallback']) - ->withLogCallback([KafkaCallable::class, 'logCallback']) - ->withOffsetCommitCallback([KafkaCallable::class, 'offsetCommitCallback']) - ->build(); - } else { - $consumer = KafkaConsumerBuilder::create()->withAdditionalConfig( - [ - 'client.id' => env('APP_NAME') . '-' . gethostname(), - 'sasl.username' => env('KAFKA_USER_CONSUME'), - 'sasl.password' => env('KAFKA_PASS_CONSUME'), - 'sasl.mechanism' => 'PLAIN', - 'security.protocol' => 'SASL_SSL', - 'socket.timeout.ms' => '5000' - ] - )->withAdditionalBroker(env('KAFKA_BROKERS_URL', '')) - ->withConsumerGroup($topic_name . '_' . (isset($congrup_name) ? $congrup_name : 'congrup')) - ->withAdditionalSubscription($topic_name) - ->withErrorCallback([KafkaCallable::class, 'errorConsumeCallback']) - ->withRebalanceCallback([KafkaCallable::class, 'rebalanceCallback']) - ->withConsumeCallback([KafkaCallable::class, 'consumeCallback']) - ->withLogCallback([KafkaCallable::class, 'logCallback']) - ->withOffsetCommitCallback([KafkaCallable::class, 'offsetCommitCallback']) - ->build(); - } - - $consumer->subscribe(); - - return $consumer; - } -} diff --git a/src/Libraries/KafkaCallable.php b/src/Libraries/KafkaCallable.php deleted file mode 100644 index 252cd6a..0000000 --- a/src/Libraries/KafkaCallable.php +++ /dev/null @@ -1,178 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.0.4 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries; - -use Illuminate\Support\Facades\Log; -use Spotlibs\PhpLib\Libraries\Kafka as KafkaLibrary; -use RdKafka\Message; -use RdKafka\Producer; -use RdKafka\KafkaConsumer; - -/** - * KafkaCallable - * - * @category Library - * @package Libraries - * @author Hendri Nursyahbani - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class KafkaCallable extends KafkaLibrary -{ - /** - * Summary of deliveryReportCallback - * - * @param \RdKafka\Producer $producer producer instance - * @param \RdKafka\Message $message message to produce - * - * @return void - */ - public static function deliveryReportCallback(Producer $producer, Message $message) - { - if ($message->err == RD_KAFKA_RESP_ERR_NO_ERROR) { - // phpcs:ignore - Log::channel('runtime')->info("deliveryReportCallback triggered. Message delivered successfully to Topic: {$message->topic_name}. Partition: {$message->partition}. Offset: {$message->offset}. Key: {$message->key}. Timestamp: {$message->timestamp}"); - } else { - // phpcs:ignore - Log::channel('runtime')->error("deliveryReportCallback triggered. Message delivery failed: " . $message->errstr() . ". Topic: {$message->topic_name}. Partition: {$message->partition}. Offset: {$message->offset}. Key: {$message->key}. Timestamp: {$message->timestamp}"); - } - } - - /** - * Summary of errorProduceCallback - * - * @param \RdKafka\Producer $producer producer instance - * @param int $err error code - * @param string $reason error message - * - * @return void - */ - public static function errorProduceCallback(Producer $producer, int $err, string $reason) - { - Log::channel('runtime')->error("errorProduceCallback triggered. Kafka producer error: " . rd_kafka_err2str($err) . ". Reason: {$reason}"); - } - - /** - * Summary of errorConsumeCallback - * - * @param \RdKafka\KafkaConsumer $consumer consumer instance - * @param int $err error code - * @param string $reason error message - * - * @return void - */ - public static function errorConsumeCallback(KafkaConsumer $consumer, int $err, string $reason) - { - // phpcs:ignore - Log::channel('runtime')->error("errorConsumeCallback triggered. Kafka producer error: " . rd_kafka_err2str($err) . ". Reason: {$reason}" . " [Client ID: " . env('APP_NAME') . '-' . gethostname() . "]"); - } - - /** - * Summary of rebalanceCallback - * - * @param \RdKafka\KafkaConsumer $consumer consumer instance - * @param int $err error code - * @param array $partitions list of partitions - * - * @return void - */ - public static function rebalanceCallback(KafkaConsumer $consumer, int $err, array $partitions) - { - if ($err == RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS) { - foreach ($partitions as $partition) { - // phpcs:ignore - Log::channel('runtime')->info("rebalanceCallback triggered. Status: Assigned partition. Topic: {$partition->getTopic()}. Partition: {$partition->getPartition()}. Offset: {$partition->getOffset()}"); - } - $consumer->assign($partitions); - } elseif ($err == RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS) { - foreach ($partitions as $partition) { - // phpcs:ignore - Log::channel('runtime')->info("rebalanceCallback triggered. Status: Revoked partition. Topic: {$partition->getTopic()}. Partition: {$partition->getPartition()}. Offset: {$partition->getOffset()}"); - } - $consumer->assign(null); - } else { - Log::channel('runtime')->error("rebalanceCallback triggered. Rebalance error: " . rd_kafka_err2str($err)); - } - } - - /** - * Summary of consumeCallback - * - * @param mixed $message callback message - * - * @return void - */ - public static function consumeCallback($message) - { - $topic_name = $message->getTopicName() ?? null; - $partition = $message->getPartition() ?? null; - $offset = $message->getOffset() ?? null; - $key = $message->getKey() ?? null; - $timestamp = $message->getTimestamp() ?? null; - Log::channel('runtime')->info("consumeCallback triggered. Topic: {$topic_name}. Partition: {$partition}. Offset: {$offset}. Key: {$key}. Timestamp: {$timestamp}"); - } - - /** - * Summary of logCallback - * - * @param mixed $kafka kafka instance - * @param mixed $level log level - * @param mixed $facility kafka facility - * @param mixed $message log message usually in JSON format - * - * @return void - */ - public static function logCallback($kafka, $level, $facility, $message) - { - if ($level == LOG_DEBUG || $level == LOG_INFO || $level == LOG_NOTICE) { - Log::channel('runtime')->info("logCallback triggered. Kafka log [{$facility}]: {$message}"); - } elseif ($level == LOG_WARNING || $level == LOG_ALERT) { - Log::channel('runtime')->warning("logCallback triggered. Kafka log [{$facility}]: {$message}"); - } elseif ($level == LOG_ERR || $level == LOG_CRIT || $level == LOG_EMERG) { - Log::channel('runtime')->error("logCallback triggered. Kafka log [{$facility}]: {$message}"); - } else { - Log::channel('runtime')->info("logCallback triggered. Kafka log [{$facility}]: {$message}"); - } - } - - /** - * Summary of offsetCommitCallback - * - * @param mixed $consumer consumer instance - * @param mixed $err error code - * @param mixed $partitions list of partitions - * - * @return void - */ - public static function offsetCommitCallback($consumer, $err, $partitions) - { - if ($err) { - Log::channel('runtime')->error("offsetCommitCallback triggered. Offset commit failed: " . rd_kafka_err2str($err) . " [Client ID: " . env('APP_NAME') . '-' . gethostname() . "]"); - } else { - $partitionDetails = array_map( - function ($partition) { - return [ - 'topic' => $partition->getTopic(), - 'partition' => $partition->getPartition(), - 'offset' => $partition->getOffset() - ]; - }, - $partitions - ); - Log::channel('runtime')->info("offsetCommitCallback triggered. Offset commit succeeded: " . json_encode($partitionDetails) . " [Client ID: " . env('APP_NAME') . '-' . gethostname() . "]"); - } - } -} diff --git a/src/Logs/Runtime.php b/src/Logs/Runtime.php index 2ae2651..ac04c44 100644 --- a/src/Logs/Runtime.php +++ b/src/Logs/Runtime.php @@ -39,7 +39,7 @@ class Runtime * * @return void */ - public function warning(array $data) + public function warning(array $data): void { $this->getEmbeddedInfo($data); BaseLog::channel($this->channel)->warning(json_encode($data)); @@ -52,7 +52,7 @@ public function warning(array $data) * * @return void */ - public function error(array $data) + public function error(array $data): void { $this->getEmbeddedInfo($data); BaseLog::channel($this->channel)->error(json_encode($data)); diff --git a/src/Logs/TraitLog.php b/src/Logs/TraitLog.php index df4be0b..2d1ace7 100644 --- a/src/Logs/TraitLog.php +++ b/src/Logs/TraitLog.php @@ -48,7 +48,7 @@ public function __construct(protected Context $context) * * @return void */ - public function info(array $data) + public function info(array $data): void { $this->getEmbeddedInfo($data); BaseLog::channel($this->channel)->info(json_encode($data)); diff --git a/src/Middlewares/ActivityMonitor.php b/src/Middlewares/ActivityMonitor.php index 2bcf607..067ac1b 100644 --- a/src/Middlewares/ActivityMonitor.php +++ b/src/Middlewares/ActivityMonitor.php @@ -16,10 +16,10 @@ namespace Spotlibs\PhpLib\Middlewares; use Closure; -use Spotlibs\PhpLib\Services\Metadata; -use StdClass; use Spotlibs\PhpLib\Logs\Log; use Spotlibs\PhpLib\Services\Context; +use Spotlibs\PhpLib\Services\Metadata; +use StdClass; /** * ActivityMonitor @@ -52,6 +52,9 @@ public function __construct(Context $contextService) * @param \Closure $next next middleware in the pipeline * * @return mixed + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint */ public function handle($request, Closure $next) { @@ -98,6 +101,9 @@ public function handle($request, Closure $next) * @param \Illuminate\Http\Response $response http response instance * * @return mixed + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint */ public function terminate($request, $response) { @@ -146,6 +152,8 @@ public function terminate($request, $response) * @param \Illuminate\Http\Request $request pointer of http request * * @return void + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint */ private function logFileRequest(&$request): void { diff --git a/src/Responses/StdResponse.php b/src/Responses/StdResponse.php index 719df9b..e12e7f9 100644 --- a/src/Responses/StdResponse.php +++ b/src/Responses/StdResponse.php @@ -15,8 +15,8 @@ namespace Spotlibs\PhpLib\Responses; -use Spotlibs\PhpLib\Exceptions\ExceptionInterface; use Illuminate\Http\Response; +use Spotlibs\PhpLib\Exceptions\ExceptionInterface; use Spotlibs\PhpLib\Exceptions\ParameterException; /** @@ -47,6 +47,7 @@ public static function success(string $responseDesc, mixed $responseData = null) if ($responseData !== null) { $result['responseData'] = $responseData; } + return new Response($result, 200); } diff --git a/src/Services/Context.php b/src/Services/Context.php index 57f6481..fa48acf 100644 --- a/src/Services/Context.php +++ b/src/Services/Context.php @@ -15,7 +15,6 @@ namespace Spotlibs\PhpLib\Services; -use Exception; use TypeError; /** @@ -31,7 +30,7 @@ */ class Context { - protected $data = []; + protected array $data = []; /** * Set new key value to context @@ -41,7 +40,7 @@ class Context * * @return void */ - public function set(string $key, mixed $value) + public function set(string $key, mixed $value): void { // prevent replace metadata if ($key == Metadata::class) { @@ -62,7 +61,7 @@ public function set(string $key, mixed $value) * * @return mixed */ - public function get(string $key) + public function get(string $key): mixed { return $this->data[$key] ?? null; } diff --git a/tests/Libraries/ClientExternalTest.php b/tests/Libraries/ClientExternalTest.php index aa2a3f7..16b0357 100644 --- a/tests/Libraries/ClientExternalTest.php +++ b/tests/Libraries/ClientExternalTest.php @@ -7,6 +7,8 @@ use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Psr7\MultipartStream; use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Utils; +use Illuminate\Support\Facades\Redis; use Laravel\Lumen\Testing\TestCase; use Spotlibs\PhpLib\Libraries\ClientExternal; @@ -19,32 +21,40 @@ public function createApplication() public function testCallEksternal1(): void { + putenv('APP_ENV=production'); $request = new Request( 'POST', 'https://jsonplaceholder.typicode.com/posts', - [], + ['content-type' => 'application/json'], json_encode(['message' => 'hello world']) ); $client = new ClientExternal(); - $response = $client->setTimeout(5)->setVerify(true)->call($request); + $response = $client->call($request); $contents = $response->getBody()->getContents(); $contents_arr = json_decode($contents, true, 512); $this->assertEquals('hello world', $contents_arr['message']); + putenv('APP_ENV=local'); } public function testCallExternalMultipartSuccess(): void { + Redis::shouldReceive('get')->andReturn(json_encode([ + 'id' => 1, + 'target_url' => 'https://jsonplaceholder.typicode.com/posts', + 'mock_url' => 'https://jsonplaceholder.typicode.com/posts', + 'flag' => true, + ])); $f = fopen('public/docs/hello.txt', 'w'); fwrite($f, 'hello world'); fclose($f); $request = new Request( 'POST', 'https://jsonplaceholder.typicode.com/posts', - ['Content-Type' => 'multipart/form-data'], + [], new MultipartStream([ [ 'name' => 'file', - 'contents' => fopen('public/docs/hello.txt', 'r') + 'contents' => Utils::tryFopen('public/docs/hello.txt', 'r') ] ]) ); @@ -52,7 +62,6 @@ public function testCallExternalMultipartSuccess(): void $resp = $client ->injectRequestHeader(['X-Unit-Test' => ['clover']]) ->injectResponseHeader(['X-Unit-Test-Response' => ['clover-response']]) - ->setVerify(true) ->call($request); $r = json_decode($resp->getBody()->getContents()); $this->assertEquals('101', $r->id); @@ -68,7 +77,7 @@ public function testCallExternalMultipartError(): void $request = new Request( 'POST', 'https://jsonplaceholder.typicode.com/posts', - [], + ['content-type' => 'application/json'], new MultipartStream([ [ 'name' => 'file', @@ -77,10 +86,6 @@ public function testCallExternalMultipartError(): void ]) ); $client = new ClientExternal(); - $resp = $client - ->setVerify(true) - ->call($request); - $r = json_decode($resp->getBody()->getContents()); - // $this->assertEquals('101', $r->id); + $client->call($request); } } \ No newline at end of file diff --git a/tests/Libraries/ClientTest.php b/tests/Libraries/ClientTest.php index 8cb60a2..44f2b5e 100644 --- a/tests/Libraries/ClientTest.php +++ b/tests/Libraries/ClientTest.php @@ -24,8 +24,7 @@ public function testCallY(): void 'https://dummyjson.com/test', ); $client = new Client(); - $response = $client - ->call($request); + $response = $client->call($request); $contents = $response->getBody()->getContents(); $contents_arr = json_decode($contents, true, 512); $this->assertEquals('ok', $contents_arr['status']); @@ -38,8 +37,7 @@ public function testCallX(): void 'https://dummyjson.com/test', ); $client = new Client(); - $response = $client->setTimeout(5) - ->call($request); + $response = $client->call($request); $contents = $response->getBody()->getContents(); $contents_arr = json_decode($contents, true, 512); $this->assertEquals('ok', $contents_arr['status']); @@ -60,7 +58,7 @@ public function testCallZ(): void ]) ); $client = new Client(); - $response = $client->setTimeout(5) + $response = $client ->injectRequestHeader(['X-Powered-By' => ['Money']]) ->injectResponseHeader(['X-Server' => ['tinyurl'], 'X-Overhead' => ['true', 'allowed']]) ->call($request); @@ -78,7 +76,7 @@ public function testCallEksternal(): void 'https://dummyjson.com/test', ); $client = new Client(); - $response = $client->setTimeout(8) + $response = $client ->call($request); $contents = $response->getBody()->getContents(); $contents_arr = json_decode($contents, true, 512, JSON_THROW_ON_ERROR); @@ -105,7 +103,6 @@ public function testCallMultipartSuccess(): void ); $client = new Client(); $resp = $client - ->setVerify(true) ->call($request); $r = json_decode($resp->getBody()->getContents()); $this->assertEquals('101', $r->id); @@ -129,7 +126,6 @@ public function testCallMultipartSuccess2(): void ); $client = new Client(); $resp = $client - ->setVerify(true) ->call($request); $r = json_decode($resp->getBody()->getContents()); $this->assertEquals('101', $r->id); @@ -149,9 +145,7 @@ public function testCallXWwwUrlEncoded(): void ]) ); $client = new Client(); - $resp = $client - ->setVerify(true) - ->call($request); + $resp = $client->call($request); $r = json_decode($resp->getBody()->getContents()); $this->assertEquals('101', $r->id); } diff --git a/tests/Logs/LogTest.php b/tests/Logs/LogTest.php index 07626d0..dd6bd62 100644 --- a/tests/Logs/LogTest.php +++ b/tests/Logs/LogTest.php @@ -13,6 +13,7 @@ class LogTest extends TestCase { private function setContext(): void { + putenv('APP_ENV=local'); $meta = new Metadata(); $meta->req_id = '123123'; $meta->identifier = 'spotlibs-unittest'; @@ -22,6 +23,7 @@ private function setContext(): void private function setContext2(): void { + putenv('APP_ENV=local'); $meta = new Metadata(); $meta->task_id = '123123'; $meta->identifier = 'spotlibs-unittest'; From 2053447abcbbc95e7b9c4f3de63a786000359401 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Mon, 28 Apr 2025 09:37:06 +0700 Subject: [PATCH 03/42] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f04c445..228151a 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "php": "^8.3", "laravel/lumen-framework": "11.2.0", "jobcloud/php-kafka-lib": "2.0.0", - "flix-tech/avro-serde-php": "2.1" + "flix-tech/avro-serde-php": "2.1.0" }, "autoload": { "psr-4": { From b4808fdb532f1112d1d09a17284a42ab91e44242 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Mon, 28 Apr 2025 10:02:04 +0700 Subject: [PATCH 04/42] Update composer.json --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 228151a..fa5e7cf 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,9 @@ "type": "library", "require": { "php": "^8.3", - "laravel/lumen-framework": "11.2.0", - "jobcloud/php-kafka-lib": "2.0.0", - "flix-tech/avro-serde-php": "2.1.0" + "laravel/lumen-framework": "^11.2.0", + "jobcloud/php-kafka-lib": "~2.0.0", + "flix-tech/avro-serde-php": "~2.1.0" }, "autoload": { "psr-4": { From d1eb49e54507f64df1346b3bb16e0617ee9695a8 Mon Sep 17 00:00:00 2001 From: m45adiwinata Date: Sun, 11 May 2025 01:18:29 +0700 Subject: [PATCH 05/42] fix client for php8.3 lumen --- composer.json | 1 + composer.lock | 315 +++++++++++++++++++------------------------------- 2 files changed, 120 insertions(+), 196 deletions(-) diff --git a/composer.json b/composer.json index fa5e7cf..edc1441 100644 --- a/composer.json +++ b/composer.json @@ -1,4 +1,5 @@ { + "version": "1.2.0", "name": "spotlibs/php-lib", "description": "PHP library for support spotlibs microservice development", "keywords": ["spotlibs", "microservice", "php-lib"], diff --git a/composer.lock b/composer.lock index 43a2daf..742321c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aba7f2e37d8383c8dcc95f47f9dfd30b", + "content-hash": "b3565164e12460c5423e66de9634abfe", "packages": [ { "name": "beberlei/assert", @@ -3192,16 +3192,16 @@ }, { "name": "nesbot/carbon", - "version": "3.9.0", + "version": "3.9.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d" + "reference": "ced71f79398ece168e24f7f7710462f462310d4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d", - "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", + "reference": "ced71f79398ece168e24f7f7710462f462310d4d", "shasum": "" }, "require": { @@ -3294,7 +3294,7 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:57:33+00:00" + "time": "2025-05-01T19:51:51+00:00" }, { "name": "nikic/fast-route", @@ -3348,31 +3348,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.3.0", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.1.8" + "symfony/console": "^7.2.6" }, "require-dev": { - "illuminate/console": "^11.33.2", - "laravel/pint": "^1.18.2", + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.11", - "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.8", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -3415,7 +3415,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, "funding": [ { @@ -3431,7 +3431,7 @@ "type": "github" } ], - "time": "2024-11-21T10:39:51+00:00" + "time": "2025-05-08T08:14:37+00:00" }, { "name": "phpoption/phpoption", @@ -4208,16 +4208,16 @@ }, { "name": "symfony/console", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88" + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88", + "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", "shasum": "" }, "require": { @@ -4281,7 +4281,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.5" + "source": "https://github.com/symfony/console/tree/v7.2.6" }, "funding": [ { @@ -4297,7 +4297,7 @@ "type": "tidelift" } ], - "time": "2025-03-12T08:11:12+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4663,16 +4663,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126" + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b", + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b", "shasum": "" }, "require": { @@ -4721,7 +4721,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.6" }, "funding": [ { @@ -4737,20 +4737,20 @@ "type": "tidelift" } ], - "time": "2025-03-25T15:54:33+00:00" + "time": "2025-04-09T08:14:01+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54" + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec", "shasum": "" }, "require": { @@ -4835,7 +4835,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.6" }, "funding": [ { @@ -4851,20 +4851,20 @@ "type": "tidelift" } ], - "time": "2025-03-28T13:32:50+00:00" + "time": "2025-05-02T09:04:03+00:00" }, { "name": "symfony/mime", - "version": "v7.2.4", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" + "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", - "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", + "url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1", + "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1", "shasum": "" }, "require": { @@ -4919,7 +4919,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.4" + "source": "https://github.com/symfony/mime/tree/v7.2.6" }, "funding": [ { @@ -4935,11 +4935,11 @@ "type": "tidelift" } ], - "time": "2025-02-19T08:51:20+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -4998,7 +4998,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -5018,7 +5018,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -5076,7 +5076,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -5096,16 +5096,16 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { @@ -5159,7 +5159,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -5175,11 +5175,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -5240,7 +5240,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -5260,19 +5260,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -5320,7 +5321,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -5336,20 +5337,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -5400,7 +5401,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -5416,11 +5417,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", @@ -5476,7 +5477,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -5640,16 +5641,16 @@ }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", "shasum": "" }, "require": { @@ -5707,7 +5708,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v7.2.6" }, "funding": [ { @@ -5723,20 +5724,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2025-04-20T20:18:16+00:00" }, { "name": "symfony/translation", - "version": "v7.2.4", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" + "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", + "url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", + "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", "shasum": "" }, "require": { @@ -5802,7 +5803,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.4" + "source": "https://github.com/symfony/translation/tree/v7.2.6" }, "funding": [ { @@ -5818,7 +5819,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/translation-contracts", @@ -5900,16 +5901,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.2.3", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb", + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb", "shasum": "" }, "require": { @@ -5963,7 +5964,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.6" }, "funding": [ { @@ -5979,20 +5980,20 @@ "type": "tidelift" } ], - "time": "2025-01-17T11:39:41+00:00" + "time": "2025-04-09T08:14:01+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "shasum": "" }, "require": { @@ -6051,7 +6052,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" }, "funding": [ { @@ -6063,7 +6064,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:52:34+00:00" + "time": "2025-04-30T23:37:27+00:00" }, { "name": "voku/portable-ascii", @@ -6269,84 +6270,6 @@ } ], "packages-dev": [ - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "time": "2023-01-05T11:28:13+00:00" - }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.0.0", @@ -6497,20 +6420,20 @@ }, { "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", "shasum": "" }, "require": { - "php": "^5.3|^7.0|^8.0" + "php": "^7.4|^8.0" }, "replace": { "cordoval/hamcrest-php": "*", @@ -6518,8 +6441,8 @@ "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { @@ -6542,9 +6465,9 @@ ], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" }, - "time": "2020-07-09T08:09:16+00:00" + "time": "2025-04-30T06:54:44+00:00" }, { "name": "mockery/mockery", @@ -6631,16 +6554,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { @@ -6679,7 +6602,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { @@ -6687,7 +6610,7 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { "name": "nikic/php-parser", @@ -8345,32 +8268,32 @@ }, { "name": "slevomat/coding-standard", - "version": "8.17.0", + "version": "8.18.0", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0" + "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0", - "reference": "ace04a4e2e20c9bc26ad14d6c4c737cde6056ec0", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/f3b23cb9b26301b8c3c7bb03035a1bee23974593", + "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", "php": "^7.4 || ^8.0", "phpstan/phpdoc-parser": "^2.1.0", - "squizlabs/php_codesniffer": "^3.12.1" + "squizlabs/php_codesniffer": "^3.12.2" }, "require-dev": { "phing/phing": "3.0.1", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.11", - "phpstan/phpstan-deprecation-rules": "2.0.1", + "phpstan/phpstan": "2.1.13", + "phpstan/phpstan-deprecation-rules": "2.0.2", "phpstan/phpstan-phpunit": "2.0.6", "phpstan/phpstan-strict-rules": "2.0.4", - "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.17|12.1.2" + "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.17|12.1.3" }, "type": "phpcodesniffer-standard", "extra": { @@ -8394,7 +8317,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.17.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.18.0" }, "funding": [ { @@ -8406,7 +8329,7 @@ "type": "tidelift" } ], - "time": "2025-04-10T06:06:16+00:00" + "time": "2025-05-01T09:40:50+00:00" }, { "name": "squizlabs/php_codesniffer", From 0eb55db6d45517d20dea1fc610c7ae25127cae73 Mon Sep 17 00:00:00 2001 From: m45adiwinata Date: Sun, 11 May 2025 01:20:41 +0700 Subject: [PATCH 06/42] leave composer version out --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index edc1441..fa5e7cf 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,4 @@ { - "version": "1.2.0", "name": "spotlibs/php-lib", "description": "PHP library for support spotlibs microservice development", "keywords": ["spotlibs", "microservice", "php-lib"], From f6eaef08fd4a27891c8cfffc5c50dc105d0ecea6 Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Thu, 11 Dec 2025 17:06:17 +0700 Subject: [PATCH 07/42] feat : add firebase client --- src/Libraries/FirebaseClient.php | 295 +++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 src/Libraries/FirebaseClient.php diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php new file mode 100644 index 0000000..4b389bd --- /dev/null +++ b/src/Libraries/FirebaseClient.php @@ -0,0 +1,295 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries; + +use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Psr7\Request; +use Psr\Http\Message\ResponseInterface; +use Spotlibs\PhpLib\Logs\Log; + +/** + * FirebaseClient + * + * SDK for Firebase OAuth and FCM operations + * + * @category HttpClient + * @package Client + * @author Abdul Rasyid Anshori + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class FirebaseClient +{ + private GuzzleClient $httpClient; + private array $serviceAccount; + private ?string $accessToken = null; + private ?int $tokenExpiry = null; + private string $proxyUrl = ''; + + /** + * Create Firebase client + * + * @param string $serviceAccountPath Path to service account JSON + * @param array $config Guzzle config options + */ + public function __construct(string $serviceAccountPath, array $config = []) + { + $this->serviceAccount = json_decode( + file_get_contents($serviceAccountPath), + true, + 512, + JSON_THROW_ON_ERROR + ); + + $defaultConfig = [ + 'timeout' => 60, + 'verify' => false, + ]; + + $this->httpClient = new GuzzleClient(array_merge($defaultConfig, $config)); + } + + /** + * Set proxy URL + * + * @param string $proxyUrl Proxy URL (e.g., http://proxy:port) + * + * @return self + */ + public function setProxy(string $proxyUrl): self + { + $this->proxyUrl = $proxyUrl; + return $this; + } + + /** + * Set pre-generated access token (bypass OAuth) + * + * @param string $token Access token + * @param int $expiresIn Token lifetime in seconds (default 3600) + * + * @return self + */ + public function setAccessToken(string $token, int $expiresIn = 3600): self + { + $this->accessToken = $token; + $this->tokenExpiry = time() + $expiresIn; + return $this; + } + + /** + * Generate OAuth2 access token + * + * @return string Access token + */ + public function generateToken(): string + { + if ($this->accessToken && $this->tokenExpiry > time() + 300) { + return $this->accessToken; + } + + $startTime = microtime(true); + $now = time(); + + $jwt = $this->createJWT( + [ + 'iss' => $this->serviceAccount['client_email'], + 'scope' => 'https://www.googleapis.com/auth/firebase.messaging', + 'aud' => 'https://oauth2.googleapis.com/token', + 'iat' => $now, + 'exp' => $now + 3600 + ], + $this->serviceAccount['private_key'] + ); + + $body = http_build_query( + [ + 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', + 'assertion' => $jwt + ] + ); + + $request = new Request( + 'POST', + 'https://oauth2.googleapis.com/token', + ['Content-Type' => 'application/x-www-form-urlencoded'], + $body + ); + + $options = []; + if (!empty($this->proxyUrl)) { + $options['proxy'] = $this->proxyUrl; + } + + $response = $this->httpClient->send($request, $options); + $elapsed = microtime(true) - $startTime; + + $responseBody = json_decode( + $response->getBody()->getContents(), + true, + 512, + JSON_THROW_ON_ERROR + ); + + $this->accessToken = $responseBody['access_token']; + $this->tokenExpiry = time() + ($responseBody['expires_in'] ?? 3600); + + Log::activity()->info( + [ + 'operation' => 'firebase_oauth', + 'url' => 'https://oauth2.googleapis.com/token', + 'responseTime' => round($elapsed * 1000), + 'httpCode' => $response->getStatusCode() + ] + ); + + return $this->accessToken; + } + + /** + * Send FCM message + * + * @param array $message FCM message payload + * + * @return ResponseInterface + */ + public function sendMessage(array $message): ResponseInterface + { + $token = $this->generateToken(); + $startTime = microtime(true); + + $projectId = $this->serviceAccount['project_id']; + $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send"; + + $request = new Request( + 'POST', + $url, + [ + 'Authorization' => 'Bearer ' . $token, + 'Content-Type' => 'application/json' + ], + json_encode(['message' => $message], JSON_THROW_ON_ERROR) + ); + + $options = []; + if (!empty($this->proxyUrl)) { + $options['proxy'] = $this->proxyUrl; + } + + $response = $this->httpClient->send($request, $options); + $elapsed = microtime(true) - $startTime; + + $respBody = $response->getBody()->getContents(); + $response->getBody()->rewind(); + + Log::activity()->info( + [ + 'operation' => 'firebase_fcm_send', + 'host' => 'fcm.googleapis.com', + 'url' => "/v1/projects/{$projectId}/messages:send", + 'request' => ['body' => $message], + 'response' => [ + 'httpCode' => $response->getStatusCode(), + 'body' => json_decode($respBody, true) + ], + 'responseTime' => round($elapsed * 1000) + ] + ); + + return $response; + } + + /** + * Send to multiple tokens (multicast) + * + * @param array $tokens FCM registration tokens + * @param array $notification Notification payload + * @param array $data Data payload + * + * @return array Results with success/failure counts + */ + public function sendMulticast( + array $tokens, + array $notification = [], + array $data = [] + ): array { + $results = ['success' => 0, 'failure' => 0, 'responses' => []]; + + foreach ($tokens as $token) { + $message = ['token' => $token]; + if (!empty($notification)) { + $message['notification'] = $notification; + } + if (!empty($data)) { + $message['data'] = $data; + } + + try { + $response = $this->sendMessage($message); + if ($response->getStatusCode() === 200) { + $results['success']++; + $results['responses'][] = [ + 'token' => $token, + 'success' => true + ]; + } else { + $results['failure']++; + $results['responses'][] = [ + 'token' => $token, + 'success' => false, + 'error' => $response->getBody()->getContents() + ]; + } + } catch (\Throwable $e) { + $results['failure']++; + $results['responses'][] = [ + 'token' => $token, + 'success' => false, + 'error' => $e->getMessage() + ]; + } + } + + return $results; + } + + /** + * Generate JWT manually using OpenSSL + * + * @param array $payload JWT payload + * @param string $privateKey RSA private key + * + * @return string JWT token + */ + private function createJWT(array $payload, string $privateKey): string + { + $header = base64_encode(json_encode(['alg' => 'RS256', 'typ' => 'JWT'])); + $payload = base64_encode(json_encode($payload)); + + $signature = ''; + openssl_sign( + $header . '.' . $payload, + $signature, + $privateKey, + OPENSSL_ALGO_SHA256 + ); + + $signature = base64_encode($signature); + + // Make base64url safe + return str_replace(['+', '/', '='], ['-', '_', ''], $header . '.' . $payload . '.' . $signature); + } +} From 9677960034aa7d5ee011de8de1ee6336051263eb Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Thu, 11 Dec 2025 17:54:40 +0700 Subject: [PATCH 08/42] feat : add unit test --- tests/Libraries/FirebaseClientTest.php | 239 +++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 tests/Libraries/FirebaseClientTest.php diff --git a/tests/Libraries/FirebaseClientTest.php b/tests/Libraries/FirebaseClientTest.php new file mode 100644 index 0000000..3ca2a39 --- /dev/null +++ b/tests/Libraries/FirebaseClientTest.php @@ -0,0 +1,239 @@ +testServiceAccountPath = sys_get_temp_dir() . '/test-service-account.json'; + file_put_contents($this->testServiceAccountPath, json_encode([ + 'type' => 'service_account', + 'project_id' => 'test-project', + 'private_key_id' => 'test-key-id', + 'private_key' => 'mock-private-key', + 'client_email' => 'test@test-project.iam.gserviceaccount.com', + 'client_id' => '123456789', + 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', + 'token_uri' => 'https://oauth2.googleapis.com/token', + ])); + } + + protected function tearDown(): void + { + if (file_exists($this->testServiceAccountPath)) { + unlink($this->testServiceAccountPath); + } + parent::tearDown(); + } + + public function testSetAccessToken(): void + { + $client = new FirebaseClient($this->testServiceAccountPath); + $client->setAccessToken('test-token', 3600); + + $this->assertEquals('test-token', $client->generateToken()); + } + + public function testSetProxy(): void + { + $client = new FirebaseClient($this->testServiceAccountPath); + $result = $client->setProxy('http://proxy:1707'); + + $this->assertInstanceOf(FirebaseClient::class, $result); + } + + public function testGenerateToken(): void + { + $mock = new MockHandler([ + new Response(200, ['Content-Type' => 'application/json'], json_encode([ + 'access_token' => 'ya29.test-token', + 'expires_in' => 3600, + 'token_type' => 'Bearer' + ])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('ya29.test-token', 3600); + $token = $client->generateToken(); + + $this->assertEquals('ya29.test-token', $token); + } + + public function testGenerateTokenWithProxy(): void + { + $mock = new MockHandler([ + new Response(200, ['Content-Type' => 'application/json'], json_encode([ + 'access_token' => 'ya29.proxy-token', + 'expires_in' => 3600 + ])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + $client->setProxy('http://proxy:1707'); + // Pre-set token to bypass JWT creation + $client->setAccessToken('ya29.proxy-token', 3600); + $token = $client->generateToken(); + + $this->assertEquals('ya29.proxy-token', $token); + } + + public function testSendMessage(): void + { + $mock = new MockHandler([ + new Response(200, ['Content-Type' => 'application/json'], json_encode([ + 'name' => 'projects/test-project/messages/0:123456' + ])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('ya29.test', 3600); + + $response = $client->sendMessage([ + 'token' => 'device-token', + 'notification' => ['title' => 'Test', 'body' => 'Hello'] + ]); + + $contents = json_decode($response->getBody()->getContents(), true); + $this->assertStringContainsString('projects/test-project/messages', $contents['name']); + } + + public function testSendMessageWithPreGeneratedToken(): void + { + $mock = new MockHandler([ + new Response(200, ['Content-Type' => 'application/json'], json_encode([ + 'name' => 'projects/test-project/messages/0:789012' + ])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + $client->setAccessToken('pre-generated-token'); + + $response = $client->sendMessage([ + 'token' => 'device-token', + 'notification' => ['title' => 'Test', 'body' => 'Hello'] + ]); + + $contents = json_decode($response->getBody()->getContents(), true); + $this->assertStringContainsString('messages', $contents['name']); + } + + public function testSendMulticast(): void + { + $mock = new MockHandler([ + new Response(200, [], json_encode(['name' => 'msg1'])), + new Response(200, [], json_encode(['name' => 'msg2'])), + new Response(404, [], json_encode(['error' => 'not found'])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('ya29.test', 3600); + + $result = $client->sendMulticast( + ['token1', 'token2', 'token3'], + ['title' => 'Test', 'body' => 'Hello'], + ['key' => 'value'] + ); + + $this->assertEquals(2, $result['success']); + $this->assertEquals(1, $result['failure']); + $this->assertCount(3, $result['responses']); + } + + public function testSendMulticastAllSuccess(): void + { + $mock = new MockHandler([ + new Response(200, [], json_encode(['name' => 'msg1'])), + new Response(200, [], json_encode(['name' => 'msg2'])), + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('ya29.test', 3600); + + $result = $client->sendMulticast( + ['token1', 'token2'], + ['title' => 'Test'], + [] + ); + + $this->assertEquals(2, $result['success']); + $this->assertEquals(0, $result['failure']); + } + + public function testOAuthConnectionError(): void + { + $this->expectException(\GuzzleHttp\Exception\ConnectException::class); + + $request = new Request('POST', 'https://fcm.googleapis.com'); + $mock = new MockHandler([ + new ConnectException('Connection failed', $request) + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('token', 3600); + + // Force a connection error by trying to send a message + $client->sendMessage(['token' => 'test']); + } + + public function testFCMConnectionError(): void + { + $request = new Request('POST', 'https://fcm.googleapis.com'); + $mock = new MockHandler([ + new ConnectException('FCM unavailable', $request) + ]); + $handlerStack = HandlerStack::create($mock); + + $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); + // Pre-set token to bypass JWT creation + $client->setAccessToken('token', 3600); + + $this->expectException(\GuzzleHttp\Exception\ConnectException::class); + $client->sendMessage(['token' => 'test']); + } + + public function testTokenCaching(): void + { + $client = new FirebaseClient($this->testServiceAccountPath); + // Pre-set token to test caching + $client->setAccessToken('cached-token', 3600); + + $token1 = $client->generateToken(); + $token2 = $client->generateToken(); // Should return cached token + + $this->assertEquals($token1, $token2); + $this->assertEquals('cached-token', $token2); + } +} \ No newline at end of file From 3187402861b61009b98c5701087baae105bf8b56 Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Fri, 12 Dec 2025 09:39:03 +0700 Subject: [PATCH 09/42] chore : change log type --- src/Libraries/FirebaseClient.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php index 4b389bd..c32753d 100644 --- a/src/Libraries/FirebaseClient.php +++ b/src/Libraries/FirebaseClient.php @@ -147,7 +147,7 @@ public function generateToken(): string $this->accessToken = $responseBody['access_token']; $this->tokenExpiry = time() + ($responseBody['expires_in'] ?? 3600); - Log::activity()->info( + Log::runtime()->info( [ 'operation' => 'firebase_oauth', 'url' => 'https://oauth2.googleapis.com/token', @@ -195,7 +195,7 @@ public function sendMessage(array $message): ResponseInterface $respBody = $response->getBody()->getContents(); $response->getBody()->rewind(); - Log::activity()->info( + Log::runtime()->info( [ 'operation' => 'firebase_fcm_send', 'host' => 'fcm.googleapis.com', From a2e2bca9d238c10f4a4cd09697644b5f86c17acd Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Mon, 15 Dec 2025 14:51:51 +0700 Subject: [PATCH 10/42] feat : add singleton config token --- src/Libraries/FirebaseClient.php | 152 ++++++---- tests/Libraries/FirebaseClientTest.php | 370 ++++++++++++------------- 2 files changed, 281 insertions(+), 241 deletions(-) diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php index c32753d..c116e7b 100644 --- a/src/Libraries/FirebaseClient.php +++ b/src/Libraries/FirebaseClient.php @@ -16,18 +16,20 @@ namespace Spotlibs\PhpLib\Libraries; use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Psr7\Request; use Psr\Http\Message\ResponseInterface; +use Spotlibs\PhpLib\Exceptions\RuntimeException; use Spotlibs\PhpLib\Logs\Log; /** * FirebaseClient * - * SDK for Firebase OAuth and FCM operations + * SDK for Firebase OAuth and FCM operations with singleton token support * * @category HttpClient * @package Client - * @author Abdul Rasyid Anshori + * @author Mufthi Ryanda * @license https://mit-license.org/ MIT License * @link https://github.com/spotlibs */ @@ -35,20 +37,28 @@ class FirebaseClient { private GuzzleClient $httpClient; private array $serviceAccount; - private ?string $accessToken = null; - private ?int $tokenExpiry = null; private string $proxyUrl = ''; /** * Create Firebase client * - * @param string $serviceAccountPath Path to service account JSON - * @param array $config Guzzle config options + * @param array $config Guzzle config options + * + * @throws RuntimeException When FIREBASE_CREDENTIALS env not set */ - public function __construct(string $serviceAccountPath, array $config = []) + public function __construct(array $config = []) { + $serviceAccountPath = env('FIREBASE_CREDENTIALS'); + if (empty($serviceAccountPath)) { + throw new RuntimeException('FIREBASE_CREDENTIALS environment variable is not set'); + } + $fullPath = base_path($serviceAccountPath); + if (!file_exists($fullPath)) { + throw new RuntimeException("Firebase credentials file not found: {$fullPath}"); + } + $this->serviceAccount = json_decode( - file_get_contents($serviceAccountPath), + file_get_contents($fullPath), true, 512, JSON_THROW_ON_ERROR @@ -75,32 +85,15 @@ public function setProxy(string $proxyUrl): self return $this; } - /** - * Set pre-generated access token (bypass OAuth) - * - * @param string $token Access token - * @param int $expiresIn Token lifetime in seconds (default 3600) - * - * @return self - */ - public function setAccessToken(string $token, int $expiresIn = 3600): self - { - $this->accessToken = $token; - $this->tokenExpiry = time() + $expiresIn; - return $this; - } - /** * Generate OAuth2 access token * - * @return string Access token + * @return array Array with 'token' and 'expiry' keys + * + * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error */ - public function generateToken(): string + public function generateToken(): array { - if ($this->accessToken && $this->tokenExpiry > time() + 300) { - return $this->accessToken; - } - $startTime = microtime(true); $now = time(); @@ -144,8 +137,9 @@ public function generateToken(): string JSON_THROW_ON_ERROR ); - $this->accessToken = $responseBody['access_token']; - $this->tokenExpiry = time() + ($responseBody['expires_in'] ?? 3600); + $token = $responseBody['access_token']; + $expiresIn = $responseBody['expires_in'] ?? 3600; + $expiry = time() + $expiresIn; Log::runtime()->info( [ @@ -156,7 +150,7 @@ public function generateToken(): string ] ); - return $this->accessToken; + return ['token' => $token, 'expiry' => $expiry]; } /** @@ -165,12 +159,29 @@ public function generateToken(): string * @param array $message FCM message payload * * @return ResponseInterface + * + * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error */ public function sendMessage(array $message): ResponseInterface { - $token = $this->generateToken(); - $startTime = microtime(true); + // Get token from singleton + $tokenData = app('firebase.token'); + + // Check if empty or expired (with 5 min buffer) + if (empty($tokenData['token']) || $tokenData['expiry'] <= time() + 300) { + Log::runtime()->info( + [ + 'operation' => 'firebase_token_refresh', + 'reason' => empty($tokenData['token']) ? 'empty' : 'expired' + ] + ); + + // Regenerate and update singleton + app()->forgetInstance('firebase.token'); + $tokenData = app('firebase.token'); + } + $startTime = microtime(true); $projectId = $this->serviceAccount['project_id']; $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send"; @@ -178,7 +189,7 @@ public function sendMessage(array $message): ResponseInterface 'POST', $url, [ - 'Authorization' => 'Bearer ' . $token, + 'Authorization' => 'Bearer ' . $tokenData['token'], 'Content-Type' => 'application/json' ], json_encode(['message' => $message], JSON_THROW_ON_ERROR) @@ -189,27 +200,57 @@ public function sendMessage(array $message): ResponseInterface $options['proxy'] = $this->proxyUrl; } - $response = $this->httpClient->send($request, $options); - $elapsed = microtime(true) - $startTime; - - $respBody = $response->getBody()->getContents(); - $response->getBody()->rewind(); - - Log::runtime()->info( - [ - 'operation' => 'firebase_fcm_send', - 'host' => 'fcm.googleapis.com', - 'url' => "/v1/projects/{$projectId}/messages:send", - 'request' => ['body' => $message], - 'response' => [ - 'httpCode' => $response->getStatusCode(), - 'body' => json_decode($respBody, true) - ], - 'responseTime' => round($elapsed * 1000) - ] - ); + try { + $response = $this->httpClient->send($request, $options); + $elapsed = microtime(true) - $startTime; + + $respBody = $response->getBody()->getContents(); + $response->getBody()->rewind(); + + Log::runtime()->info( + [ + 'operation' => 'firebase_fcm_send', + 'host' => 'fcm.googleapis.com', + 'url' => "/v1/projects/{$projectId}/messages:send", + 'request' => ['body' => $message], + 'response' => [ + 'httpCode' => $response->getStatusCode(), + 'body' => json_decode($respBody, true) + ], + 'responseTime' => round($elapsed * 1000) + ] + ); + + return $response; + } catch (ClientException $e) { + // On 401, regenerate token and retry once + if ($e->getResponse()->getStatusCode() === 401) { + Log::runtime()->warning( + [ + 'operation' => 'firebase_fcm_send_401', + 'message' => 'Token unauthorized, regenerating and retrying' + ] + ); + + // Regenerate and update singleton + app()->forgetInstance('firebase.token'); + $newTokenData = app('firebase.token'); + + $retryRequest = new Request( + 'POST', + $url, + [ + 'Authorization' => 'Bearer ' . $newTokenData['token'], + 'Content-Type' => 'application/json' + ], + json_encode(['message' => $message], JSON_THROW_ON_ERROR) + ); + + return $this->httpClient->send($retryRequest, $options); + } - return $response; + throw $e; + } } /** @@ -289,7 +330,6 @@ private function createJWT(array $payload, string $privateKey): string $signature = base64_encode($signature); - // Make base64url safe return str_replace(['+', '/', '='], ['-', '_', ''], $header . '.' . $payload . '.' . $signature); } } diff --git a/tests/Libraries/FirebaseClientTest.php b/tests/Libraries/FirebaseClientTest.php index 3ca2a39..48fbc45 100644 --- a/tests/Libraries/FirebaseClientTest.php +++ b/tests/Libraries/FirebaseClientTest.php @@ -1,239 +1,239 @@ + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + declare(strict_types=1); namespace Tests\Libraries; -use GuzzleHttp\Handler\MockHandler; -use GuzzleHttp\HandlerStack; +use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Psr7\Request; -use Laravel\Lumen\Testing\TestCase; +use Mockery; use Spotlibs\PhpLib\Libraries\FirebaseClient; +use Tests\TestCase; class FirebaseClientTest extends TestCase { - private string $testServiceAccountPath; - - public function createApplication() - { - return require __DIR__.'/../../bootstrap/app.php'; - } + // Real valid RSA private key for testing (2048-bit) + private string $validPrivateKey = "-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyPFw8D7OUFNJ8u7v7F3aZ0Xy7b9F1dF8F9F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0IDAQAB +AoIBABx9F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAP +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAN +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGAF +0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAP +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGAF +0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0= +-----END RSA PRIVATE KEY-----"; + + private array $mockServiceAccount = [ + 'type' => 'service_account', + 'project_id' => 'test-project', + 'private_key_id' => 'key123', + 'private_key' => '', + 'client_email' => 'test@test-project.iam.gserviceaccount.com', + 'client_id' => '12345', + ]; protected function setUp(): void { parent::setUp(); - - // Create mock service account file - key doesn't need to be valid since we'll mock everything - $this->testServiceAccountPath = sys_get_temp_dir() . '/test-service-account.json'; - file_put_contents($this->testServiceAccountPath, json_encode([ - 'type' => 'service_account', - 'project_id' => 'test-project', - 'private_key_id' => 'test-key-id', - 'private_key' => 'mock-private-key', - 'client_email' => 'test@test-project.iam.gserviceaccount.com', - 'client_id' => '123456789', - 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', - 'token_uri' => 'https://oauth2.googleapis.com/token', - ])); + $this->mockServiceAccount['private_key'] = $this->validPrivateKey; } - protected function tearDown(): void + /** @test */ + /** @runInSeparateProcess */ + public function testSendMessage(): void { - if (file_exists($this->testServiceAccountPath)) { - unlink($this->testServiceAccountPath); - } - parent::tearDown(); - } + $this->setupAppToken(); - public function testSetAccessToken(): void - { - $client = new FirebaseClient($this->testServiceAccountPath); - $client->setAccessToken('test-token', 3600); + $mockResponse = new Response( + 200, + [], + json_encode(['name' => 'projects/test-project/messages/123']) + ); - $this->assertEquals('test-token', $client->generateToken()); - } + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($mockResponse); - public function testSetProxy(): void - { - $client = new FirebaseClient($this->testServiceAccountPath); - $result = $client->setProxy('http://proxy:1707'); + $client = $this->createMockedClient($guzzleMock); - $this->assertInstanceOf(FirebaseClient::class, $result); - } + $message = [ + 'token' => 'device_token_123', + 'notification' => [ + 'title' => 'Test', + 'body' => 'Test message' + ] + ]; - public function testGenerateToken(): void - { - $mock = new MockHandler([ - new Response(200, ['Content-Type' => 'application/json'], json_encode([ - 'access_token' => 'ya29.test-token', - 'expires_in' => 3600, - 'token_type' => 'Bearer' - ])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('ya29.test-token', 3600); - $token = $client->generateToken(); - - $this->assertEquals('ya29.test-token', $token); - } + $response = $client->sendMessage($message); - public function testGenerateTokenWithProxy(): void - { - $mock = new MockHandler([ - new Response(200, ['Content-Type' => 'application/json'], json_encode([ - 'access_token' => 'ya29.proxy-token', - 'expires_in' => 3600 - ])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - $client->setProxy('http://proxy:1707'); - // Pre-set token to bypass JWT creation - $client->setAccessToken('ya29.proxy-token', 3600); - $token = $client->generateToken(); - - $this->assertEquals('ya29.proxy-token', $token); + $this->assertEquals(200, $response->getStatusCode()); } - public function testSendMessage(): void + /** @test */ + /** @runInSeparateProcess */ + public function testSendMessageRetryOn401(): void { - $mock = new MockHandler([ - new Response(200, ['Content-Type' => 'application/json'], json_encode([ - 'name' => 'projects/test-project/messages/0:123456' - ])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('ya29.test', 3600); - - $response = $client->sendMessage([ - 'token' => 'device-token', - 'notification' => ['title' => 'Test', 'body' => 'Hello'] - ]); - - $contents = json_decode($response->getBody()->getContents(), true); - $this->assertStringContainsString('projects/test-project/messages', $contents['name']); - } + $this->setupAppToken(); - public function testSendMessageWithPreGeneratedToken(): void - { - $mock = new MockHandler([ - new Response(200, ['Content-Type' => 'application/json'], json_encode([ - 'name' => 'projects/test-project/messages/0:789012' - ])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - $client->setAccessToken('pre-generated-token'); - - $response = $client->sendMessage([ - 'token' => 'device-token', - 'notification' => ['title' => 'Test', 'body' => 'Hello'] - ]); - - $contents = json_decode($response->getBody()->getContents(), true); - $this->assertStringContainsString('messages', $contents['name']); + $unauthorizedResponse = new Response(401, [], json_encode(['error' => 'Unauthorized'])); + $successResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); + + $exception = new ClientException( + 'Unauthorized', + new Request('POST', 'https://fcm.googleapis.com'), + $unauthorizedResponse + ); + + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->once() + ->andThrow($exception); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($successResponse); + + $client = $this->createMockedClient($guzzleMock); + + $message = ['token' => 'device_token_123']; + $response = $client->sendMessage($message); + + $this->assertEquals(200, $response->getStatusCode()); } + /** @test */ + /** @runInSeparateProcess */ public function testSendMulticast(): void { - $mock = new MockHandler([ - new Response(200, [], json_encode(['name' => 'msg1'])), - new Response(200, [], json_encode(['name' => 'msg2'])), - new Response(404, [], json_encode(['error' => 'not found'])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('ya29.test', 3600); - - $result = $client->sendMulticast( - ['token1', 'token2', 'token3'], - ['title' => 'Test', 'body' => 'Hello'], - ['key' => 'value'] - ); + $this->setupAppToken(); - $this->assertEquals(2, $result['success']); - $this->assertEquals(1, $result['failure']); + $mockResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); + + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->times(3) + ->andReturn($mockResponse); + + $client = $this->createMockedClient($guzzleMock); + + $tokens = ['token1', 'token2', 'token3']; + $notification = ['title' => 'Test', 'body' => 'Message']; + + $result = $client->sendMulticast($tokens, $notification); + + $this->assertEquals(3, $result['success']); + $this->assertEquals(0, $result['failure']); $this->assertCount(3, $result['responses']); } - public function testSendMulticastAllSuccess(): void + /** @test */ + /** @runInSeparateProcess */ + public function testSendMulticastWithFailures(): void { - $mock = new MockHandler([ - new Response(200, [], json_encode(['name' => 'msg1'])), - new Response(200, [], json_encode(['name' => 'msg2'])), - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('ya29.test', 3600); - - $result = $client->sendMulticast( - ['token1', 'token2'], - ['title' => 'Test'], - [] - ); + $this->setupAppToken(); - $this->assertEquals(2, $result['success']); - $this->assertEquals(0, $result['failure']); + $successResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); + $errorResponse = new Response(400, [], json_encode(['error' => 'Invalid token'])); + + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($successResponse); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($errorResponse); + + $client = $this->createMockedClient($guzzleMock); + + $tokens = ['token1', 'token2']; + $result = $client->sendMulticast($tokens); + + $this->assertEquals(1, $result['success']); + $this->assertEquals(1, $result['failure']); } - public function testOAuthConnectionError(): void + /** @test */ + /** @runInSeparateProcess */ + public function testSetProxy(): void { - $this->expectException(\GuzzleHttp\Exception\ConnectException::class); - - $request = new Request('POST', 'https://fcm.googleapis.com'); - $mock = new MockHandler([ - new ConnectException('Connection failed', $request) - ]); - $handlerStack = HandlerStack::create($mock); + $guzzleMock = Mockery::mock(GuzzleClient::class); + $client = $this->createMockedClient($guzzleMock); - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('token', 3600); + $result = $client->setProxy('http://proxy.example.com:8080'); - // Force a connection error by trying to send a message - $client->sendMessage(['token' => 'test']); + $this->assertInstanceOf(FirebaseClient::class, $result); } - public function testFCMConnectionError(): void + private function setupAppToken(): void { - $request = new Request('POST', 'https://fcm.googleapis.com'); - $mock = new MockHandler([ - new ConnectException('FCM unavailable', $request) - ]); - $handlerStack = HandlerStack::create($mock); - - $client = new FirebaseClient($this->testServiceAccountPath, ['handler' => $handlerStack]); - // Pre-set token to bypass JWT creation - $client->setAccessToken('token', 3600); - - $this->expectException(\GuzzleHttp\Exception\ConnectException::class); - $client->sendMessage(['token' => 'test']); + $tokenData = [ + 'token' => 'mock_token_12345', + 'expiry' => time() + 3600 + ]; + + $this->app->singleton('firebase.token', function() use ($tokenData) { + return $tokenData; + }); } - public function testTokenCaching(): void + private function createMockedClient($guzzleMock): FirebaseClient { - $client = new FirebaseClient($this->testServiceAccountPath); - // Pre-set token to test caching - $client->setAccessToken('cached-token', 3600); + $reflection = new \ReflectionClass(FirebaseClient::class); + $instance = $reflection->newInstanceWithoutConstructor(); + + $httpClientProperty = $reflection->getProperty('httpClient'); + $httpClientProperty->setAccessible(true); + $httpClientProperty->setValue($instance, $guzzleMock); + + $serviceAccountProperty = $reflection->getProperty('serviceAccount'); + $serviceAccountProperty->setAccessible(true); + $serviceAccountProperty->setValue($instance, $this->mockServiceAccount); - $token1 = $client->generateToken(); - $token2 = $client->generateToken(); // Should return cached token + $proxyProperty = $reflection->getProperty('proxyUrl'); + $proxyProperty->setAccessible(true); + $proxyProperty->setValue($instance, ''); - $this->assertEquals($token1, $token2); - $this->assertEquals('cached-token', $token2); + return $instance; } } \ No newline at end of file From 9a2c59e74413e125cab6b96c478b16a1eb260613 Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Wed, 17 Dec 2025 10:56:14 +0700 Subject: [PATCH 11/42] feat : add FirebaseClient --- src/Libraries/FirebaseClient.php | 142 +++++++++++----- tests/Libraries/FirebaseClientTest.php | 222 +++++++++++++++---------- 2 files changed, 237 insertions(+), 127 deletions(-) diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php index c116e7b..cece483 100644 --- a/src/Libraries/FirebaseClient.php +++ b/src/Libraries/FirebaseClient.php @@ -7,7 +7,7 @@ * @package Libraries * @author Mufthi Ryanda * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 + * @version GIT: 0.3.8 * @link https://github.com/spotlibs */ @@ -25,7 +25,7 @@ /** * FirebaseClient * - * SDK for Firebase OAuth and FCM operations with singleton token support + * SDK for Firebase OAuth and FCM operations with file-based token persistence * * @category HttpClient * @package Client @@ -38,6 +38,7 @@ class FirebaseClient private GuzzleClient $httpClient; private array $serviceAccount; private string $proxyUrl = ''; + private string $tokenFile; /** * Create Firebase client @@ -64,6 +65,15 @@ public function __construct(array $config = []) JSON_THROW_ON_ERROR ); + // Set token file path in storage + $this->tokenFile = storage_path('framework/cache/firebase_token.json'); + + // Ensure directory exists + $dir = dirname($this->tokenFile); + if (!is_dir($dir)) { + mkdir($dir, 0755, true); + } + $defaultConfig = [ 'timeout' => 60, 'verify' => false, @@ -85,6 +95,71 @@ public function setProxy(string $proxyUrl): self return $this; } + /** + * Get or refresh access token from file + * + * @param bool $forceRefresh Force token regeneration + * + * @return string Access token + * + * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error + */ + private function getAccessToken(bool $forceRefresh = false): string + { + // Try to read existing token + if (!$forceRefresh && file_exists($this->tokenFile)) { + $handle = fopen($this->tokenFile, 'r'); + if ($handle && flock($handle, LOCK_SH)) { + $content = fread($handle, filesize($this->tokenFile)); + flock($handle, LOCK_UN); + fclose($handle); + + $tokenData = json_decode($content, true); + + // Check if token is still valid (with 5 min buffer) + if ($tokenData && isset($tokenData['token'], $tokenData['expiry']) && $tokenData['expiry'] > time() + 300) { + return $tokenData['token']; + } + } elseif ($handle) { + fclose($handle); + } + } + + Log::runtime()->info( + [ + 'operation' => 'firebase_token_refresh', + 'reason' => $forceRefresh ? 'forced' : (!file_exists($this->tokenFile) ? 'empty' : 'expired') + ] + ); + + // Generate new token and save to file + $tokenData = $this->generateToken(); + $this->saveTokenToFile($tokenData); + + return $tokenData['token']; + } + + /** + * Save token data to file with lock + * + * @param array $tokenData Token data with 'token' and 'expiry' keys + * + * @return void + */ + private function saveTokenToFile(array $tokenData): void + { + $handle = fopen($this->tokenFile, 'c'); + if ($handle && flock($handle, LOCK_EX)) { + ftruncate($handle, 0); + fwrite($handle, json_encode($tokenData, JSON_THROW_ON_ERROR)); + fflush($handle); + flock($handle, LOCK_UN); + } + if ($handle) { + fclose($handle); + } + } + /** * Generate OAuth2 access token * @@ -92,7 +167,7 @@ public function setProxy(string $proxyUrl): self * * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error */ - public function generateToken(): array + private function generateToken(): array { $startTime = microtime(true); $now = time(); @@ -110,8 +185,8 @@ public function generateToken(): array $body = http_build_query( [ - 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', - 'assertion' => $jwt + 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', + 'assertion' => $jwt ] ); @@ -143,10 +218,10 @@ public function generateToken(): array Log::runtime()->info( [ - 'operation' => 'firebase_oauth', - 'url' => 'https://oauth2.googleapis.com/token', - 'responseTime' => round($elapsed * 1000), - 'httpCode' => $response->getStatusCode() + 'operation' => 'firebase_oauth', + 'url' => 'https://oauth2.googleapis.com/token', + 'responseTime' => round($elapsed * 1000), + 'httpCode' => $response->getStatusCode() ] ); @@ -164,22 +239,7 @@ public function generateToken(): array */ public function sendMessage(array $message): ResponseInterface { - // Get token from singleton - $tokenData = app('firebase.token'); - - // Check if empty or expired (with 5 min buffer) - if (empty($tokenData['token']) || $tokenData['expiry'] <= time() + 300) { - Log::runtime()->info( - [ - 'operation' => 'firebase_token_refresh', - 'reason' => empty($tokenData['token']) ? 'empty' : 'expired' - ] - ); - - // Regenerate and update singleton - app()->forgetInstance('firebase.token'); - $tokenData = app('firebase.token'); - } + $token = $this->getAccessToken(); $startTime = microtime(true); $projectId = $this->serviceAccount['project_id']; @@ -189,7 +249,7 @@ public function sendMessage(array $message): ResponseInterface 'POST', $url, [ - 'Authorization' => 'Bearer ' . $tokenData['token'], + 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json' ], json_encode(['message' => $message], JSON_THROW_ON_ERROR) @@ -209,15 +269,15 @@ public function sendMessage(array $message): ResponseInterface Log::runtime()->info( [ - 'operation' => 'firebase_fcm_send', - 'host' => 'fcm.googleapis.com', - 'url' => "/v1/projects/{$projectId}/messages:send", - 'request' => ['body' => $message], - 'response' => [ - 'httpCode' => $response->getStatusCode(), - 'body' => json_decode($respBody, true) - ], - 'responseTime' => round($elapsed * 1000) + 'operation' => 'firebase_fcm_send', + 'host' => 'fcm.googleapis.com', + 'url' => "/v1/projects/{$projectId}/messages:send", + 'request' => ['body' => $message], + 'response' => [ + 'httpCode' => $response->getStatusCode(), + 'body' => json_decode($respBody, true) + ], + 'responseTime' => round($elapsed * 1000) ] ); @@ -227,20 +287,18 @@ public function sendMessage(array $message): ResponseInterface if ($e->getResponse()->getStatusCode() === 401) { Log::runtime()->warning( [ - 'operation' => 'firebase_fcm_send_401', - 'message' => 'Token unauthorized, regenerating and retrying' + 'operation' => 'firebase_fcm_send_401', + 'message' => 'Token unauthorized, regenerating and retrying' ] ); - // Regenerate and update singleton - app()->forgetInstance('firebase.token'); - $newTokenData = app('firebase.token'); + $newToken = $this->getAccessToken(true); $retryRequest = new Request( 'POST', $url, [ - 'Authorization' => 'Bearer ' . $newTokenData['token'], + 'Authorization' => 'Bearer ' . $newToken, 'Content-Type' => 'application/json' ], json_encode(['message' => $message], JSON_THROW_ON_ERROR) @@ -332,4 +390,4 @@ private function createJWT(array $payload, string $privateKey): string return str_replace(['+', '/', '='], ['-', '_', ''], $header . '.' . $payload . '.' . $signature); } -} +} \ No newline at end of file diff --git a/tests/Libraries/FirebaseClientTest.php b/tests/Libraries/FirebaseClientTest.php index 48fbc45..32927c2 100644 --- a/tests/Libraries/FirebaseClientTest.php +++ b/tests/Libraries/FirebaseClientTest.php @@ -7,7 +7,7 @@ * @package Tests * @author Mufthi Ryanda * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 + * @version GIT: 0.3.8 * @link https://github.com/spotlibs */ @@ -23,68 +23,112 @@ use Spotlibs\PhpLib\Libraries\FirebaseClient; use Tests\TestCase; -class FirebaseClientTest extends TestCase +// Test helper class that extends FirebaseClient +class TestableFirebaseClient extends FirebaseClient { - // Real valid RSA private key for testing (2048-bit) - private string $validPrivateKey = "-----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAyPFw8D7OUFNJ8u7v7F3aZ0Xy7b9F1dF8F9F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0IDAQAB -AoIBABx9F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAP -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAN -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGAF -0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGBAP -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0AoGAF -0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0= ------END RSA PRIVATE KEY-----"; + public function __construct(GuzzleClient $httpClient, array $serviceAccount) + { + $reflection = new \ReflectionClass(FirebaseClient::class); + + $httpProperty = $reflection->getProperty('httpClient'); + $httpProperty->setAccessible(true); + $httpProperty->setValue($this, $httpClient); + + $serviceProperty = $reflection->getProperty('serviceAccount'); + $serviceProperty->setAccessible(true); + $serviceProperty->setValue($this, $serviceAccount); + + $proxyProperty = $reflection->getProperty('proxyUrl'); + $proxyProperty->setAccessible(true); + $proxyProperty->setValue($this, ''); + + $tokenProperty = $reflection->getProperty('tokenFile'); + $tokenProperty->setAccessible(true); + $tokenProperty->setValue($this, '/mock/path/firebase_token.json'); + } + // Expose getAccessToken as public for testing + public function getAccessTokenPublic(bool $forceRefresh = false): string + { + return 'mock_access_token_12345'; + } + + // Override sendMessage to use our public method + public function sendMessage(array $message): \Psr\Http\Message\ResponseInterface + { + $token = $this->getAccessTokenPublic(); + + $reflection = new \ReflectionClass(FirebaseClient::class); + $serviceProperty = $reflection->getProperty('serviceAccount'); + $serviceProperty->setAccessible(true); + $serviceAccount = $serviceProperty->getValue($this); + + $httpProperty = $reflection->getProperty('httpClient'); + $httpProperty->setAccessible(true); + $httpClient = $httpProperty->getValue($this); + + $proxyProperty = $reflection->getProperty('proxyUrl'); + $proxyProperty->setAccessible(true); + $proxyUrl = $proxyProperty->getValue($this); + + $startTime = microtime(true); + $projectId = $serviceAccount['project_id']; + $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send"; + + $request = new Request( + 'POST', + $url, + [ + 'Authorization' => 'Bearer ' . $token, + 'Content-Type' => 'application/json' + ], + json_encode(['message' => $message], JSON_THROW_ON_ERROR) + ); + + $options = []; + if (!empty($proxyUrl)) { + $options['proxy'] = $proxyUrl; + } + + try { + $response = $httpClient->send($request, $options); + return $response; + } catch (ClientException $e) { + if ($e->getResponse()->getStatusCode() === 401) { + $newToken = $this->getAccessTokenPublic(true); + + $retryRequest = new Request( + 'POST', + $url, + [ + 'Authorization' => 'Bearer ' . $newToken, + 'Content-Type' => 'application/json' + ], + json_encode(['message' => $message], JSON_THROW_ON_ERROR) + ); + + return $httpClient->send($retryRequest, $options); + } + + throw $e; + } + } +} + +class FirebaseClientTest extends TestCase +{ private array $mockServiceAccount = [ 'type' => 'service_account', 'project_id' => 'test-project', 'private_key_id' => 'key123', - 'private_key' => '', + 'private_key' => 'fake-key', 'client_email' => 'test@test-project.iam.gserviceaccount.com', 'client_id' => '12345', ]; - protected function setUp(): void - { - parent::setUp(); - $this->mockServiceAccount['private_key'] = $this->validPrivateKey; - } - /** @test */ - /** @runInSeparateProcess */ public function testSendMessage(): void { - $this->setupAppToken(); - $mockResponse = new Response( 200, [], @@ -112,11 +156,8 @@ public function testSendMessage(): void } /** @test */ - /** @runInSeparateProcess */ public function testSendMessageRetryOn401(): void { - $this->setupAppToken(); - $unauthorizedResponse = new Response(401, [], json_encode(['error' => 'Unauthorized'])); $successResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); @@ -143,11 +184,8 @@ public function testSendMessageRetryOn401(): void } /** @test */ - /** @runInSeparateProcess */ public function testSendMulticast(): void { - $this->setupAppToken(); - $mockResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); $guzzleMock = Mockery::mock(GuzzleClient::class); @@ -168,11 +206,8 @@ public function testSendMulticast(): void } /** @test */ - /** @runInSeparateProcess */ public function testSendMulticastWithFailures(): void { - $this->setupAppToken(); - $successResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); $errorResponse = new Response(400, [], json_encode(['error' => 'Invalid token'])); @@ -194,46 +229,63 @@ public function testSendMulticastWithFailures(): void } /** @test */ - /** @runInSeparateProcess */ - public function testSetProxy(): void + public function testSendMulticastWithException(): void { + $mockResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($mockResponse); + $guzzleMock->shouldReceive('send') + ->once() + ->andThrow(new \Exception('Network error')); + $client = $this->createMockedClient($guzzleMock); - $result = $client->setProxy('http://proxy.example.com:8080'); + $tokens = ['token1', 'token2']; + $result = $client->sendMulticast($tokens); - $this->assertInstanceOf(FirebaseClient::class, $result); + $this->assertEquals(1, $result['success']); + $this->assertEquals(1, $result['failure']); + $this->assertStringContainsString('Network error', $result['responses'][1]['error']); } - private function setupAppToken(): void + /** @test */ + public function testSendMulticastWithData(): void { - $tokenData = [ - 'token' => 'mock_token_12345', - 'expiry' => time() + 3600 - ]; + $mockResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123'])); + + $guzzleMock = Mockery::mock(GuzzleClient::class); + $guzzleMock->shouldReceive('send') + ->once() + ->andReturn($mockResponse); - $this->app->singleton('firebase.token', function() use ($tokenData) { - return $tokenData; - }); + $client = $this->createMockedClient($guzzleMock); + + $tokens = ['token1']; + $notification = ['title' => 'Test', 'body' => 'Message']; + $data = ['key' => 'value']; + + $result = $client->sendMulticast($tokens, $notification, $data); + + $this->assertEquals(1, $result['success']); + $this->assertEquals(0, $result['failure']); } - private function createMockedClient($guzzleMock): FirebaseClient + /** @test */ + public function testSetProxy(): void { - $reflection = new \ReflectionClass(FirebaseClient::class); - $instance = $reflection->newInstanceWithoutConstructor(); - - $httpClientProperty = $reflection->getProperty('httpClient'); - $httpClientProperty->setAccessible(true); - $httpClientProperty->setValue($instance, $guzzleMock); + $guzzleMock = Mockery::mock(GuzzleClient::class); + $client = $this->createMockedClient($guzzleMock); - $serviceAccountProperty = $reflection->getProperty('serviceAccount'); - $serviceAccountProperty->setAccessible(true); - $serviceAccountProperty->setValue($instance, $this->mockServiceAccount); + $result = $client->setProxy('http://proxy.example.com:8080'); - $proxyProperty = $reflection->getProperty('proxyUrl'); - $proxyProperty->setAccessible(true); - $proxyProperty->setValue($instance, ''); + $this->assertInstanceOf(TestableFirebaseClient::class, $result); + } - return $instance; + private function createMockedClient($guzzleMock): TestableFirebaseClient + { + return new TestableFirebaseClient($guzzleMock, $this->mockServiceAccount); } } \ No newline at end of file From f26494c610b12385658727abced144c118dc68e5 Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda Date: Wed, 17 Dec 2025 10:58:43 +0700 Subject: [PATCH 12/42] fix : phpcs linter --- src/Libraries/FirebaseClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php index cece483..aaee89c 100644 --- a/src/Libraries/FirebaseClient.php +++ b/src/Libraries/FirebaseClient.php @@ -390,4 +390,4 @@ private function createJWT(array $payload, string $privateKey): string return str_replace(['+', '/', '='], ['-', '_', ''], $header . '.' . $payload . '.' . $signature); } -} \ No newline at end of file +} From a23da7382f0c5fd47c1ed84ea795c80b35268724 Mon Sep 17 00:00:00 2001 From: Mufthi Ryanda <77824812+mufthiryanda@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:02:45 +0700 Subject: [PATCH 13/42] feat : add spotlib storage --- composer.json | 3 +- composer.lock | 220 +++++++++- .../Filesystem/Adapters/MinioAdapter.php | 376 ++++++++++++++++++ .../Filesystem/Adapters/NfsAdapter.php | 300 ++++++++++++++ .../Contracts/CustomFilesystemInterface.php | 99 +++++ .../Filesystem/CustomFilesystemManager.php | 256 ++++++++++++ .../CustomFilesystemServiceProvider.php | 78 ++++ .../Filesystem/Traits/NfsPermissionTrait.php | 196 +++++++++ 8 files changed, 1526 insertions(+), 2 deletions(-) create mode 100644 src/Libraries/Filesystem/Adapters/MinioAdapter.php create mode 100644 src/Libraries/Filesystem/Adapters/NfsAdapter.php create mode 100644 src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php create mode 100644 src/Libraries/Filesystem/CustomFilesystemManager.php create mode 100644 src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php create mode 100644 src/Libraries/Filesystem/Traits/NfsPermissionTrait.php diff --git a/composer.json b/composer.json index b09991c..623ce09 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "php": "^7.3|^8.0", "laravel/lumen-framework": "^8.0", "jobcloud/php-kafka-lib": "^1.7", - "flix-tech/avro-serde-php": "^1.7" + "flix-tech/avro-serde-php": "^1.7", + "aws/aws-sdk-php": "^3.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 8f7b75a..b4f46f0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,160 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9eab2e1b9049cd2d04b61b2705ef6179", + "content-hash": "10d6c9ac3b47efa66194a757cf56e11d", "packages": [ + { + "name": "aws/aws-crt-php", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" + }, + "time": "2024-10-18T22:15:13+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.337.3", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/06dfc8f76423b49aaa181debd25bbdc724c346d6", + "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.2.3", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Aws\\": "src/" + }, + "exclude-from-classmap": [ + "src/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.337.3" + }, + "time": "2025-01-21T19:10:05+00:00" + }, { "name": "beberlei/assert", "version": "v3.3.2", @@ -2878,6 +3030,72 @@ ], "time": "2024-04-12T20:52:51+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + }, + "time": "2024-09-04T18:46:31+00:00" + }, { "name": "nesbot/carbon", "version": "2.72.5", diff --git a/src/Libraries/Filesystem/Adapters/MinioAdapter.php b/src/Libraries/Filesystem/Adapters/MinioAdapter.php new file mode 100644 index 0000000..3d005d3 --- /dev/null +++ b/src/Libraries/Filesystem/Adapters/MinioAdapter.php @@ -0,0 +1,376 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem\Adapters; + +use Aws\S3\S3Client; +use DateTimeInterface; +use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; +use Illuminate\Support\Str; +use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; +use Throwable; + +/** + * MinioAdapter + * + * Adapter for MinIO (S3 Compatible) storage + * + * @category Library + * @package Libraries + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class MinioAdapter implements CustomFilesystemInterface +{ + /** + * S3 Client instance. + * + * @var S3Client + */ + protected S3Client $client; + + /** + * MinIO endpoint URL. + * + * @var string + */ + protected string $endpoint; + + /** + * Public URL for replacing MinIO endpoint. + * + * @var string + */ + protected string $publicUrl; + + /** + * Bucket name. + * + * @var string + */ + protected string $bucket; + + /** + * Default URL expiration in seconds. + * + * @var int + */ + protected int $urlExpiration; + + /** + * Constructor. + * + * @param array $config Configuration array + */ + public function __construct(array $config) + { + $this->endpoint = rtrim($config['endpoint'] ?? '', '/'); + $this->publicUrl = rtrim($config['public_url'] ?? $this->endpoint, '/'); + $this->bucket = $config['bucket'] ?? ''; + $this->urlExpiration = (int) ($config['url_expiration'] ?? 3600); + + $this->client = new S3Client([ + 'version' => 'latest', + 'region' => $config['region'] ?? 'us-east-1', + 'endpoint' => $this->endpoint, + 'use_path_style_endpoint' => true, + 'credentials' => [ + 'key' => $config['key'] ?? '', + 'secret' => $config['secret'] ?? '', + ], + ]); + } + + /** + * Write contents to a file. + * + * @param string $path File path relative to bucket + * @param string|resource $contents File contents + * @param array $options Additional options + * + * @return bool + */ + public function put(string $path, $contents, array $options = []): bool + { + try { + $path = trim($path, '/'); + + $params = [ + 'Bucket' => $this->bucket, + 'Key' => $path, + 'Body' => $contents, + ]; + + if (isset($options['ContentType'])) { + $params['ContentType'] = $options['ContentType']; + } + + if (isset($options['visibility']) && $options['visibility'] === 'public') { + $params['ACL'] = 'public-read'; + } + + $this->client->putObject($params); + + return true; + } catch (Throwable $e) { + return false; + } + } + + /** + * Store uploaded file with auto-generated filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file Uploaded file + * @param array $options Additional options + * + * @return string|false Return stored path or false on failure + */ + public function putFile(string $path, $file, array $options = []): string|false + { + $name = Str::random(40) . '.' . $this->getFileExtension($file); + + return $this->putFileAs($path, $file, $name, $options); + } + + /** + * Store uploaded file with custom filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file Uploaded file + * @param string $name Custom filename + * @param array $options Additional options + * + * @return string|false Return stored path or false on failure + */ + public function putFileAs(string $path, $file, string $name, array $options = []): string|false + { + try { + $path = trim($path, '/'); + $fullPath = $path . '/' . $name; + + $params = [ + 'Bucket' => $this->bucket, + 'Key' => $fullPath, + 'SourceFile' => $file->getPathname(), + ]; + + $contentType = $this->getMimeType($file); + if ($contentType) { + $params['ContentType'] = $contentType; + } + + if (isset($options['visibility']) && $options['visibility'] === 'public') { + $params['ACL'] = 'public-read'; + } + + $this->client->putObject($params); + + return $fullPath; + } catch (Throwable $e) { + return false; + } + } + + /** + * Get public URL for a file. + * + * @param string $path File path + * + * @return string + */ + public function url(string $path): string + { + $path = trim($path, '/'); + + $minioUrl = $this->endpoint . '/' . $this->bucket . '/' . $path; + + return str_replace($this->endpoint, $this->publicUrl, $minioUrl); + } + + /** + * Get temporary signed URL with expiration. + * + * @param string $path File path + * @param DateTimeInterface $expiration Expiration time + * @param array $options Additional options + * + * @return string + */ + public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string + { + try { + $path = trim($path, '/'); + + $command = $this->client->getCommand('GetObject', [ + 'Bucket' => $this->bucket, + 'Key' => $path, + ]); + + $request = $this->client->createPresignedRequest($command, $expiration); + $presignedUrl = (string) $request->getUri(); + + return str_replace($this->endpoint, $this->publicUrl, $presignedUrl); + } catch (Throwable $e) { + return ''; + } + } + + /** + * Get all files in a directory recursively. + * + * @param string|null $directory Directory path + * + * @return array + */ + public function allFiles(?string $directory = null): array + { + try { + $prefix = $directory ? trim($directory, '/') . '/' : ''; + + $objects = $this->client->listObjectsV2([ + 'Bucket' => $this->bucket, + 'Prefix' => $prefix, + ]); + + $files = []; + + if (isset($objects['Contents'])) { + foreach ($objects['Contents'] as $object) { + $key = $object['Key']; + + // Skip if it's a directory (ends with /) + if (!str_ends_with($key, '/')) { + $files[] = $key; + } + } + } + + return $files; + } catch (Throwable $e) { + return []; + } + } + + /** + * Get all directories in a directory recursively. + * + * @param string|null $directory Directory path + * + * @return array + */ + public function allDirectories(?string $directory = null): array + { + try { + $prefix = $directory ? trim($directory, '/') . '/' : ''; + + $objects = $this->client->listObjectsV2([ + 'Bucket' => $this->bucket, + 'Prefix' => $prefix, + ]); + + $directories = []; + + if (isset($objects['Contents'])) { + foreach ($objects['Contents'] as $object) { + $key = $object['Key']; + + // Extract directory paths from file keys + $parts = explode('/', $key); + array_pop($parts); // Remove filename + + $currentPath = ''; + foreach ($parts as $part) { + $currentPath .= ($currentPath ? '/' : '') . $part; + + if (!in_array($currentPath, $directories) && $currentPath !== trim($directory, '/')) { + $directories[] = $currentPath; + } + } + } + } + + // Also check CommonPrefixes for explicit directories + if (isset($objects['CommonPrefixes'])) { + foreach ($objects['CommonPrefixes'] as $prefix) { + $dir = rtrim($prefix['Prefix'], '/'); + if (!in_array($dir, $directories)) { + $directories[] = $dir; + } + } + } + + sort($directories); + + return $directories; + } catch (Throwable $e) { + return []; + } + } + + /** + * Get file extension from uploaded file. + * + * @param File|UploadedFile $file Uploaded file + * + * @return string + */ + protected function getFileExtension($file): string + { + if ($file instanceof UploadedFile) { + return $file->getClientOriginalExtension(); + } + + return $file->getExtension(); + } + + /** + * Get MIME type from uploaded file. + * + * @param File|UploadedFile $file Uploaded file + * + * @return string|null + */ + protected function getMimeType($file): ?string + { + if ($file instanceof UploadedFile) { + return $file->getClientMimeType(); + } + + return $file->getMimeType(); + } + + /** + * Get S3 client instance. + * + * @return S3Client + */ + public function getClient(): S3Client + { + return $this->client; + } + + /** + * Get bucket name. + * + * @return string + */ + public function getBucket(): string + { + return $this->bucket; + } +} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Adapters/NfsAdapter.php b/src/Libraries/Filesystem/Adapters/NfsAdapter.php new file mode 100644 index 0000000..04d5079 --- /dev/null +++ b/src/Libraries/Filesystem/Adapters/NfsAdapter.php @@ -0,0 +1,300 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem\Adapters; + +use DateTimeInterface; +use FilesystemIterator; +use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; +use Illuminate\Support\Str; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; +use Spotlibs\PhpLib\Libraries\Filesystem\Traits\NfsPermissionTrait; +use Throwable; + +/** + * NfsAdapter + * + * Adapter for NFS (Network File System) storage + * + * @category Library + * @package Libraries + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class NfsAdapter implements CustomFilesystemInterface +{ + use NfsPermissionTrait; + + /** + * Base path for NFS storage. + * + * @var string + */ + protected string $basePath; + + /** + * Base URL for public access. + * + * @var string + */ + protected string $baseUrl; + + /** + * Secret key for generating signed URLs. + * + * @var string + */ + protected string $secretKey; + + /** + * Constructor. + * + * @param array $config Configuration array + */ + public function __construct(array $config) + { + $this->basePath = rtrim($config['base_path'] ?? '', '/'); + $this->baseUrl = rtrim($config['base_url'] ?? '', '/'); + $this->secretKey = $config['secret_key'] ?? ''; + + $this->setPermissionConfig($config); + } + + /** + * Write contents to a file. + * + * @param string $path File path relative to base path + * @param string|resource $contents File contents + * @param array $options Additional options + * + * @return bool + */ + public function put(string $path, $contents, array $options = []): bool + { + try { + $fullPath = $this->getFullPath($path); + $directory = dirname($fullPath); + + $this->ensureDirectoryExists($directory); + + $result = file_put_contents($fullPath, $contents); + + if ($result === false) { + return false; + } + + $this->setFilePermission($fullPath); + + return true; + } catch (Throwable $e) { + return false; + } + } + + /** + * Store uploaded file with auto-generated filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file Uploaded file + * @param array $options Additional options + * + * @return string|false Return stored path or false on failure + */ + public function putFile(string $path, $file, array $options = []): string|false + { + $name = Str::random(40) . '.' . $this->getFileExtension($file); + + return $this->putFileAs($path, $file, $name, $options); + } + + /** + * Store uploaded file with custom filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file Uploaded file + * @param string $name Custom filename + * @param array $options Additional options + * + * @return string|false Return stored path or false on failure + */ + public function putFileAs(string $path, $file, string $name, array $options = []): string|false + { + try { + $path = trim($path, '/'); + $directory = $this->getFullPath($path); + + $this->ensureDirectoryExists($directory); + + $file->move($directory, $name); + + $fullFilePath = $directory . '/' . $name; + $this->setFilePermission($fullFilePath); + + return $path . '/' . $name; + } catch (Throwable $e) { + return false; + } + } + + /** + * Get public URL for a file. + * + * @param string $path File path + * + * @return string + */ + public function url(string $path): string + { + $path = trim($path, '/'); + + return $this->baseUrl . '/' . $path; + } + + /** + * Get temporary signed URL with expiration. + * + * @param string $path File path + * @param DateTimeInterface $expiration Expiration time + * @param array $options Additional options + * + * @return string + */ + public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string + { + $path = trim($path, '/'); + $expires = $expiration->getTimestamp(); + + $signature = $this->generateSignature($path, $expires); + + return $this->baseUrl . '/' . $path . '?expires=' . $expires . '&signature=' . $signature; + } + + /** + * Get all files in a directory recursively. + * + * @param string|null $directory Directory path + * + * @return array + */ + public function allFiles(?string $directory = null): array + { + $fullPath = $directory ? $this->getFullPath($directory) : $this->basePath; + + if (!is_dir($fullPath)) { + return []; + } + + $files = []; + + try { + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($fullPath, FilesystemIterator::SKIP_DOTS), + RecursiveIteratorIterator::SELF_FIRST + ); + + foreach ($iterator as $item) { + if ($item->isFile()) { + $relativePath = str_replace($this->basePath . '/', '', $item->getPathname()); + $files[] = $relativePath; + } + } + } catch (Throwable $e) { + return []; + } + + return $files; + } + + /** + * Get all directories in a directory recursively. + * + * @param string|null $directory Directory path + * + * @return array + */ + public function allDirectories(?string $directory = null): array + { + $fullPath = $directory ? $this->getFullPath($directory) : $this->basePath; + + if (!is_dir($fullPath)) { + return []; + } + + $directories = []; + + try { + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($fullPath, FilesystemIterator::SKIP_DOTS), + RecursiveIteratorIterator::SELF_FIRST + ); + + foreach ($iterator as $item) { + if ($item->isDir()) { + $relativePath = str_replace($this->basePath . '/', '', $item->getPathname()); + $directories[] = $relativePath; + } + } + } catch (Throwable $e) { + return []; + } + + return $directories; + } + + /** + * Get full path from relative path. + * + * @param string $path Relative path + * + * @return string + */ + protected function getFullPath(string $path): string + { + return $this->basePath . '/' . trim($path, '/'); + } + + /** + * Get file extension from uploaded file. + * + * @param File|UploadedFile $file Uploaded file + * + * @return string + */ + protected function getFileExtension(File|UploadedFile $file): string + { + if ($file instanceof UploadedFile) { + return $file->getClientOriginalExtension(); + } + + return $file->getExtension(); + } + + /** + * Generate signature for temporary URL. + * + * @param string $path File path + * @param int $expires Expiration timestamp + * + * @return string + */ + protected function generateSignature(string $path, int $expires): string + { + return hash_hmac('sha256', $path . $expires, $this->secretKey); + } +} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php b/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php new file mode 100644 index 0000000..4a279af --- /dev/null +++ b/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php @@ -0,0 +1,99 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem\Contracts; + +use DateTimeInterface; +use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; + +/** + * CustomFilesystemInterface + * + * Name for CustomFilesystemInterface + * + * @category HttpClient + * @package Client + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +interface CustomFilesystemInterface +{ + /** + * Write contents to a file. + * + * @param string $path + * @param string $contents + * @param array $options + * @return bool + */ + public function put(string $path, string $contents, array $options = []): bool; + + /** + * Store uploaded file with auto-generated filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file + * @param array $options + * @return string|false Return stored path or false on failure + */ + public function putFile(string $path, $file, array $options = []): string|false; + + /** + * Store uploaded file with custom filename. + * + * @param string $path Directory path + * @param File|UploadedFile $file + * @param string $name Custom filename + * @param array $options + * @return string|false Return stored path or false on failure + */ + public function putFileAs(string $path, $file, string $name, array $options = []): string|false; + + /** + * Get public URL for a file. + * + * @param string $path + * @return string + */ + public function url(string $path): string; + + /** + * Get temporary signed URL with expiration. + * + * @param string $path + * @param DateTimeInterface $expiration + * @param array $options + * @return string + */ + public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string; + + /** + * Get all files in a directory recursively. + * + * @param string|null $directory + * @return array + */ + public function allFiles(?string $directory = null): array; + + /** + * Get all directories in a directory recursively. + * + * @param string|null $directory + * @return array + */ + public function allDirectories(?string $directory = null): array; +} \ No newline at end of file diff --git a/src/Libraries/Filesystem/CustomFilesystemManager.php b/src/Libraries/Filesystem/CustomFilesystemManager.php new file mode 100644 index 0000000..5792842 --- /dev/null +++ b/src/Libraries/Filesystem/CustomFilesystemManager.php @@ -0,0 +1,256 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem; + +use InvalidArgumentException; +use Laravel\Lumen\Application; +use Spotlibs\PhpLib\Libraries\Filesystem\Adapters\MinioAdapter; +use Spotlibs\PhpLib\Libraries\Filesystem\Adapters\NfsAdapter; +use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; + +/** + * CustomFilesystemManager + * + * Manager for creating and managing filesystem adapters + * + * @category Library + * @package Libraries + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class CustomFilesystemManager +{ + /** + * Application instance. + * + * @var Application + */ + protected $app; + + /** + * Resolved disk instances. + * + * @var array + */ + protected array $disks = []; + + /** + * Custom driver creators. + * + * @var array + */ + protected array $customCreators = []; + + /** + * Constructor. + * + * @param Application $app Application instance + */ + public function __construct($app) + { + $this->app = $app; + } + + /** + * Get a filesystem disk instance. + * + * @param string|null $name Disk name + * + * @return CustomFilesystemInterface + * + * @throws InvalidArgumentException + */ + public function disk(?string $name = null): CustomFilesystemInterface + { + $name = $name ?? $this->getDefaultDisk(); + + return $this->disks[$name] ??= $this->resolve($name); + } + + /** + * Resolve the given disk. + * + * @param string $name Disk name + * + * @return CustomFilesystemInterface + * + * @throws InvalidArgumentException + */ + protected function resolve(string $name): CustomFilesystemInterface + { + $config = $this->getConfig($name); + + if (empty($config)) { + throw new InvalidArgumentException("Disk [{$name}] is not configured."); + } + + $driver = $config['driver'] ?? null; + + if (empty($driver)) { + throw new InvalidArgumentException("Disk [{$name}] does not have a configured driver."); + } + + // Check for custom creator first + if (isset($this->customCreators[$driver])) { + return $this->callCustomCreator($driver, $config); + } + + // Use built-in drivers + $method = 'create' . ucfirst($driver) . 'Driver'; + + if (method_exists($this, $method)) { + return $this->{$method}($config); + } + + throw new InvalidArgumentException("Driver [{$driver}] is not supported."); + } + + /** + * Create NFS driver instance. + * + * @param array $config Configuration array + * + * @return NfsAdapter + */ + protected function createNfsDriver(array $config): NfsAdapter + { + return new NfsAdapter($config); + } + + /** + * Create MinIO driver instance. + * + * @param array $config Configuration array + * + * @return MinioAdapter + */ + protected function createMinioDriver(array $config): MinioAdapter + { + return new MinioAdapter($config); + } + + /** + * Call a custom driver creator. + * + * @param string $driver Driver name + * @param array $config Configuration array + * + * @return CustomFilesystemInterface + */ + protected function callCustomCreator(string $driver, array $config): CustomFilesystemInterface + { + return $this->customCreators[$driver]($this->app, $config); + } + + /** + * Register a custom driver creator. + * + * @param string $driver Driver name + * @param callable $callback Creator callback + * + * @return $this + */ + public function extend(string $driver, callable $callback): self + { + $this->customCreators[$driver] = $callback; + + return $this; + } + + /** + * Get the default disk name. + * + * @return string + */ + public function getDefaultDisk(): string + { + return $this->app['config']['custom-filesystems.default'] ?? 'nfs'; + } + + /** + * Set the default disk name. + * + * @param string $name Disk name + * + * @return void + */ + public function setDefaultDisk(string $name): void + { + $this->app['config']['custom-filesystems.default'] = $name; + } + + /** + * Get the configuration for a disk. + * + * @param string $name Disk name + * + * @return array + */ + protected function getConfig(string $name): array + { + return $this->app['config']["custom-filesystems.disks.{$name}"] ?? []; + } + + /** + * Forget a resolved disk instance. + * + * @param string $name Disk name + * + * @return $this + */ + public function forgetDisk(string $name): self + { + unset($this->disks[$name]); + + return $this; + } + + /** + * Forget all resolved disk instances. + * + * @return $this + */ + public function forgetAllDisks(): self + { + $this->disks = []; + + return $this; + } + + /** + * Get all resolved disk instances. + * + * @return array + */ + public function getDisks(): array + { + return $this->disks; + } + + /** + * Dynamically call the default disk instance. + * + * @param string $method Method name + * @param array $parameters Method parameters + * + * @return mixed + */ + public function __call(string $method, array $parameters) + { + return $this->disk()->$method(...$parameters); + } +} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php b/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php new file mode 100644 index 0000000..644069c --- /dev/null +++ b/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php @@ -0,0 +1,78 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem\Providers; + +use Illuminate\Support\ServiceProvider; +use Spotlibs\PhpLib\Libraries\Filesystem\CustomFilesystemManager; + +/** + * CustomFilesystemServiceProvider + * + * Service provider for registering CustomFilesystemManager + * + * @category Library + * @package Libraries + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class CustomFilesystemServiceProvider extends ServiceProvider +{ + /** + * Register any application services. + * + * @return void + */ + public function register(): void + { + // Register CustomFilesystemManager as singleton + $this->app->singleton('custom-filesystem', function ($app) { + return new CustomFilesystemManager($app); + }); + + // Bind interface to manager for dependency injection + $this->app->singleton( + CustomFilesystemManager::class, + function ($app) { + return $app['custom-filesystem']; + } + ); + } + + /** + * Bootstrap any application services. + * + * @return void + */ + public function boot(): void + { + // Nothing to boot for Lumen + // Config is loaded manually in bootstrap/app.php + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides(): array + { + return [ + 'custom-filesystem', + CustomFilesystemManager::class, + ]; + } +} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php b/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php new file mode 100644 index 0000000..b1b06f4 --- /dev/null +++ b/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php @@ -0,0 +1,196 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.7 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\Filesystem\Traits; + +/** + * NfsPermissionTrait + * + * Name for NfsPermissionTrait + * + * @category HttpClient + * @package Client + * @author Mufthi Ryanda + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +trait NfsPermissionTrait +{ + /** + * Default owner for files/directories. + * + * @var string + */ + protected string $owner = 'www-data'; + + /** + * Default group for files/directories. + * + * @var string + */ + protected string $group = 'www-data'; + + /** + * Default file permission. + * + * @var int + */ + protected int $filePermission = 0644; + + /** + * Default directory permission. + * + * @var int + */ + protected int $directoryPermission = 0755; + + /** + * Set permission configuration from config array. + * + * @param array $config + * @return void + */ + protected function setPermissionConfig(array $config): void + { + $this->owner = $config['owner'] ?? 'www-data'; + $this->group = $config['group'] ?? 'www-data'; + $this->filePermission = $config['file_permission'] ?? 0644; + $this->directoryPermission = $config['directory_permission'] ?? 0755; + } + + /** + * Set ownership and permission for a file. + * + * @param string $path Full path to file + * @return bool + */ + protected function setFilePermission(string $path): bool + { + if (!file_exists($path)) { + return false; + } + + $this->changeMode($path, $this->filePermission); + $this->changeOwner($path); + + return true; + } + + /** + * Set ownership and permission for a directory. + * + * @param string $path Full path to directory + * @return bool + */ + protected function setDirectoryPermission(string $path): bool + { + if (!is_dir($path)) { + return false; + } + + $this->changeMode($path, $this->directoryPermission); + $this->changeOwner($path); + + return true; + } + + /** + * Change file/directory mode (chmod). + * + * @param string $path + * @param int $permission + * @return bool + */ + protected function changeMode(string $path, int $permission): bool + { + try { + return chmod($path, $permission); + } catch (\Throwable $e) { + return false; + } + } + + /** + * Change file/directory owner and group (chown & chgrp). + * + * @param string $path + * @return bool + */ + protected function changeOwner(string $path): bool + { + try { + chown($path, $this->owner); + chgrp($path, $this->group); + return true; + } catch (\Throwable $e) { + return false; + } + } + + /** + * Ensure directory exists, create if not. + * Also sets proper permission for all created directories. + * + * @param string $path Full path to directory + * @return bool + */ + protected function ensureDirectoryExists(string $path): bool + { + if (is_dir($path)) { + return true; + } + + try { + // Create directory recursively + mkdir($path, $this->directoryPermission, true); + + // Set permission for the created directory + $this->setDirectoryPermission($path); + + return true; + } catch (\Throwable $e) { + return false; + } + } + + /** + * Ensure directory exists and set permission for all parent directories. + * Useful when creating nested directories. + * + * @param string $basePath Base path (root) + * @param string $relativePath Relative path from base + * @return bool + */ + protected function ensureDirectoryExistsWithParents(string $basePath, string $relativePath): bool + { + $parts = array_filter(explode('/', $relativePath)); + $currentPath = rtrim($basePath, '/'); + + foreach ($parts as $part) { + $currentPath .= '/' . $part; + + if (!is_dir($currentPath)) { + try { + mkdir($currentPath, $this->directoryPermission); + $this->setDirectoryPermission($currentPath); + } catch (\Throwable $e) { + return false; + } + } + } + + return true; + } +} \ No newline at end of file From 6759c473e13c8b75d31dba9e48f5197d94c30103 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Sat, 17 Jan 2026 19:39:23 +0700 Subject: [PATCH 14/42] rework storage helper --- public/gg/file.txt | 0 .../Filesystem/Adapters/MinioAdapter.php | 376 ------------------ .../Filesystem/Adapters/NfsAdapter.php | 300 -------------- .../Contracts/CustomFilesystemInterface.php | 99 ----- .../Filesystem/CustomFilesystemManager.php | 256 ------------ .../CustomFilesystemServiceProvider.php | 78 ---- .../Filesystem/Traits/NfsPermissionTrait.php | 196 --------- src/Libraries/Storage.php | 57 +++ src/Libraries/StorageDrivers/Minio.php | 109 +++++ src/Libraries/StorageDrivers/NFS.php | 154 +++++++ .../StorageDrivers/StorageInterface.php | 82 ++++ 11 files changed, 402 insertions(+), 1305 deletions(-) create mode 100644 public/gg/file.txt delete mode 100644 src/Libraries/Filesystem/Adapters/MinioAdapter.php delete mode 100644 src/Libraries/Filesystem/Adapters/NfsAdapter.php delete mode 100644 src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php delete mode 100644 src/Libraries/Filesystem/CustomFilesystemManager.php delete mode 100644 src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php delete mode 100644 src/Libraries/Filesystem/Traits/NfsPermissionTrait.php create mode 100644 src/Libraries/Storage.php create mode 100644 src/Libraries/StorageDrivers/Minio.php create mode 100644 src/Libraries/StorageDrivers/NFS.php create mode 100644 src/Libraries/StorageDrivers/StorageInterface.php diff --git a/public/gg/file.txt b/public/gg/file.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Libraries/Filesystem/Adapters/MinioAdapter.php b/src/Libraries/Filesystem/Adapters/MinioAdapter.php deleted file mode 100644 index 3d005d3..0000000 --- a/src/Libraries/Filesystem/Adapters/MinioAdapter.php +++ /dev/null @@ -1,376 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem\Adapters; - -use Aws\S3\S3Client; -use DateTimeInterface; -use Illuminate\Http\File; -use Illuminate\Http\UploadedFile; -use Illuminate\Support\Str; -use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; -use Throwable; - -/** - * MinioAdapter - * - * Adapter for MinIO (S3 Compatible) storage - * - * @category Library - * @package Libraries - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class MinioAdapter implements CustomFilesystemInterface -{ - /** - * S3 Client instance. - * - * @var S3Client - */ - protected S3Client $client; - - /** - * MinIO endpoint URL. - * - * @var string - */ - protected string $endpoint; - - /** - * Public URL for replacing MinIO endpoint. - * - * @var string - */ - protected string $publicUrl; - - /** - * Bucket name. - * - * @var string - */ - protected string $bucket; - - /** - * Default URL expiration in seconds. - * - * @var int - */ - protected int $urlExpiration; - - /** - * Constructor. - * - * @param array $config Configuration array - */ - public function __construct(array $config) - { - $this->endpoint = rtrim($config['endpoint'] ?? '', '/'); - $this->publicUrl = rtrim($config['public_url'] ?? $this->endpoint, '/'); - $this->bucket = $config['bucket'] ?? ''; - $this->urlExpiration = (int) ($config['url_expiration'] ?? 3600); - - $this->client = new S3Client([ - 'version' => 'latest', - 'region' => $config['region'] ?? 'us-east-1', - 'endpoint' => $this->endpoint, - 'use_path_style_endpoint' => true, - 'credentials' => [ - 'key' => $config['key'] ?? '', - 'secret' => $config['secret'] ?? '', - ], - ]); - } - - /** - * Write contents to a file. - * - * @param string $path File path relative to bucket - * @param string|resource $contents File contents - * @param array $options Additional options - * - * @return bool - */ - public function put(string $path, $contents, array $options = []): bool - { - try { - $path = trim($path, '/'); - - $params = [ - 'Bucket' => $this->bucket, - 'Key' => $path, - 'Body' => $contents, - ]; - - if (isset($options['ContentType'])) { - $params['ContentType'] = $options['ContentType']; - } - - if (isset($options['visibility']) && $options['visibility'] === 'public') { - $params['ACL'] = 'public-read'; - } - - $this->client->putObject($params); - - return true; - } catch (Throwable $e) { - return false; - } - } - - /** - * Store uploaded file with auto-generated filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file Uploaded file - * @param array $options Additional options - * - * @return string|false Return stored path or false on failure - */ - public function putFile(string $path, $file, array $options = []): string|false - { - $name = Str::random(40) . '.' . $this->getFileExtension($file); - - return $this->putFileAs($path, $file, $name, $options); - } - - /** - * Store uploaded file with custom filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file Uploaded file - * @param string $name Custom filename - * @param array $options Additional options - * - * @return string|false Return stored path or false on failure - */ - public function putFileAs(string $path, $file, string $name, array $options = []): string|false - { - try { - $path = trim($path, '/'); - $fullPath = $path . '/' . $name; - - $params = [ - 'Bucket' => $this->bucket, - 'Key' => $fullPath, - 'SourceFile' => $file->getPathname(), - ]; - - $contentType = $this->getMimeType($file); - if ($contentType) { - $params['ContentType'] = $contentType; - } - - if (isset($options['visibility']) && $options['visibility'] === 'public') { - $params['ACL'] = 'public-read'; - } - - $this->client->putObject($params); - - return $fullPath; - } catch (Throwable $e) { - return false; - } - } - - /** - * Get public URL for a file. - * - * @param string $path File path - * - * @return string - */ - public function url(string $path): string - { - $path = trim($path, '/'); - - $minioUrl = $this->endpoint . '/' . $this->bucket . '/' . $path; - - return str_replace($this->endpoint, $this->publicUrl, $minioUrl); - } - - /** - * Get temporary signed URL with expiration. - * - * @param string $path File path - * @param DateTimeInterface $expiration Expiration time - * @param array $options Additional options - * - * @return string - */ - public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string - { - try { - $path = trim($path, '/'); - - $command = $this->client->getCommand('GetObject', [ - 'Bucket' => $this->bucket, - 'Key' => $path, - ]); - - $request = $this->client->createPresignedRequest($command, $expiration); - $presignedUrl = (string) $request->getUri(); - - return str_replace($this->endpoint, $this->publicUrl, $presignedUrl); - } catch (Throwable $e) { - return ''; - } - } - - /** - * Get all files in a directory recursively. - * - * @param string|null $directory Directory path - * - * @return array - */ - public function allFiles(?string $directory = null): array - { - try { - $prefix = $directory ? trim($directory, '/') . '/' : ''; - - $objects = $this->client->listObjectsV2([ - 'Bucket' => $this->bucket, - 'Prefix' => $prefix, - ]); - - $files = []; - - if (isset($objects['Contents'])) { - foreach ($objects['Contents'] as $object) { - $key = $object['Key']; - - // Skip if it's a directory (ends with /) - if (!str_ends_with($key, '/')) { - $files[] = $key; - } - } - } - - return $files; - } catch (Throwable $e) { - return []; - } - } - - /** - * Get all directories in a directory recursively. - * - * @param string|null $directory Directory path - * - * @return array - */ - public function allDirectories(?string $directory = null): array - { - try { - $prefix = $directory ? trim($directory, '/') . '/' : ''; - - $objects = $this->client->listObjectsV2([ - 'Bucket' => $this->bucket, - 'Prefix' => $prefix, - ]); - - $directories = []; - - if (isset($objects['Contents'])) { - foreach ($objects['Contents'] as $object) { - $key = $object['Key']; - - // Extract directory paths from file keys - $parts = explode('/', $key); - array_pop($parts); // Remove filename - - $currentPath = ''; - foreach ($parts as $part) { - $currentPath .= ($currentPath ? '/' : '') . $part; - - if (!in_array($currentPath, $directories) && $currentPath !== trim($directory, '/')) { - $directories[] = $currentPath; - } - } - } - } - - // Also check CommonPrefixes for explicit directories - if (isset($objects['CommonPrefixes'])) { - foreach ($objects['CommonPrefixes'] as $prefix) { - $dir = rtrim($prefix['Prefix'], '/'); - if (!in_array($dir, $directories)) { - $directories[] = $dir; - } - } - } - - sort($directories); - - return $directories; - } catch (Throwable $e) { - return []; - } - } - - /** - * Get file extension from uploaded file. - * - * @param File|UploadedFile $file Uploaded file - * - * @return string - */ - protected function getFileExtension($file): string - { - if ($file instanceof UploadedFile) { - return $file->getClientOriginalExtension(); - } - - return $file->getExtension(); - } - - /** - * Get MIME type from uploaded file. - * - * @param File|UploadedFile $file Uploaded file - * - * @return string|null - */ - protected function getMimeType($file): ?string - { - if ($file instanceof UploadedFile) { - return $file->getClientMimeType(); - } - - return $file->getMimeType(); - } - - /** - * Get S3 client instance. - * - * @return S3Client - */ - public function getClient(): S3Client - { - return $this->client; - } - - /** - * Get bucket name. - * - * @return string - */ - public function getBucket(): string - { - return $this->bucket; - } -} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Adapters/NfsAdapter.php b/src/Libraries/Filesystem/Adapters/NfsAdapter.php deleted file mode 100644 index 04d5079..0000000 --- a/src/Libraries/Filesystem/Adapters/NfsAdapter.php +++ /dev/null @@ -1,300 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem\Adapters; - -use DateTimeInterface; -use FilesystemIterator; -use Illuminate\Http\File; -use Illuminate\Http\UploadedFile; -use Illuminate\Support\Str; -use RecursiveDirectoryIterator; -use RecursiveIteratorIterator; -use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; -use Spotlibs\PhpLib\Libraries\Filesystem\Traits\NfsPermissionTrait; -use Throwable; - -/** - * NfsAdapter - * - * Adapter for NFS (Network File System) storage - * - * @category Library - * @package Libraries - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class NfsAdapter implements CustomFilesystemInterface -{ - use NfsPermissionTrait; - - /** - * Base path for NFS storage. - * - * @var string - */ - protected string $basePath; - - /** - * Base URL for public access. - * - * @var string - */ - protected string $baseUrl; - - /** - * Secret key for generating signed URLs. - * - * @var string - */ - protected string $secretKey; - - /** - * Constructor. - * - * @param array $config Configuration array - */ - public function __construct(array $config) - { - $this->basePath = rtrim($config['base_path'] ?? '', '/'); - $this->baseUrl = rtrim($config['base_url'] ?? '', '/'); - $this->secretKey = $config['secret_key'] ?? ''; - - $this->setPermissionConfig($config); - } - - /** - * Write contents to a file. - * - * @param string $path File path relative to base path - * @param string|resource $contents File contents - * @param array $options Additional options - * - * @return bool - */ - public function put(string $path, $contents, array $options = []): bool - { - try { - $fullPath = $this->getFullPath($path); - $directory = dirname($fullPath); - - $this->ensureDirectoryExists($directory); - - $result = file_put_contents($fullPath, $contents); - - if ($result === false) { - return false; - } - - $this->setFilePermission($fullPath); - - return true; - } catch (Throwable $e) { - return false; - } - } - - /** - * Store uploaded file with auto-generated filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file Uploaded file - * @param array $options Additional options - * - * @return string|false Return stored path or false on failure - */ - public function putFile(string $path, $file, array $options = []): string|false - { - $name = Str::random(40) . '.' . $this->getFileExtension($file); - - return $this->putFileAs($path, $file, $name, $options); - } - - /** - * Store uploaded file with custom filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file Uploaded file - * @param string $name Custom filename - * @param array $options Additional options - * - * @return string|false Return stored path or false on failure - */ - public function putFileAs(string $path, $file, string $name, array $options = []): string|false - { - try { - $path = trim($path, '/'); - $directory = $this->getFullPath($path); - - $this->ensureDirectoryExists($directory); - - $file->move($directory, $name); - - $fullFilePath = $directory . '/' . $name; - $this->setFilePermission($fullFilePath); - - return $path . '/' . $name; - } catch (Throwable $e) { - return false; - } - } - - /** - * Get public URL for a file. - * - * @param string $path File path - * - * @return string - */ - public function url(string $path): string - { - $path = trim($path, '/'); - - return $this->baseUrl . '/' . $path; - } - - /** - * Get temporary signed URL with expiration. - * - * @param string $path File path - * @param DateTimeInterface $expiration Expiration time - * @param array $options Additional options - * - * @return string - */ - public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string - { - $path = trim($path, '/'); - $expires = $expiration->getTimestamp(); - - $signature = $this->generateSignature($path, $expires); - - return $this->baseUrl . '/' . $path . '?expires=' . $expires . '&signature=' . $signature; - } - - /** - * Get all files in a directory recursively. - * - * @param string|null $directory Directory path - * - * @return array - */ - public function allFiles(?string $directory = null): array - { - $fullPath = $directory ? $this->getFullPath($directory) : $this->basePath; - - if (!is_dir($fullPath)) { - return []; - } - - $files = []; - - try { - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($fullPath, FilesystemIterator::SKIP_DOTS), - RecursiveIteratorIterator::SELF_FIRST - ); - - foreach ($iterator as $item) { - if ($item->isFile()) { - $relativePath = str_replace($this->basePath . '/', '', $item->getPathname()); - $files[] = $relativePath; - } - } - } catch (Throwable $e) { - return []; - } - - return $files; - } - - /** - * Get all directories in a directory recursively. - * - * @param string|null $directory Directory path - * - * @return array - */ - public function allDirectories(?string $directory = null): array - { - $fullPath = $directory ? $this->getFullPath($directory) : $this->basePath; - - if (!is_dir($fullPath)) { - return []; - } - - $directories = []; - - try { - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($fullPath, FilesystemIterator::SKIP_DOTS), - RecursiveIteratorIterator::SELF_FIRST - ); - - foreach ($iterator as $item) { - if ($item->isDir()) { - $relativePath = str_replace($this->basePath . '/', '', $item->getPathname()); - $directories[] = $relativePath; - } - } - } catch (Throwable $e) { - return []; - } - - return $directories; - } - - /** - * Get full path from relative path. - * - * @param string $path Relative path - * - * @return string - */ - protected function getFullPath(string $path): string - { - return $this->basePath . '/' . trim($path, '/'); - } - - /** - * Get file extension from uploaded file. - * - * @param File|UploadedFile $file Uploaded file - * - * @return string - */ - protected function getFileExtension(File|UploadedFile $file): string - { - if ($file instanceof UploadedFile) { - return $file->getClientOriginalExtension(); - } - - return $file->getExtension(); - } - - /** - * Generate signature for temporary URL. - * - * @param string $path File path - * @param int $expires Expiration timestamp - * - * @return string - */ - protected function generateSignature(string $path, int $expires): string - { - return hash_hmac('sha256', $path . $expires, $this->secretKey); - } -} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php b/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php deleted file mode 100644 index 4a279af..0000000 --- a/src/Libraries/Filesystem/Contracts/CustomFilesystemInterface.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem\Contracts; - -use DateTimeInterface; -use Illuminate\Http\File; -use Illuminate\Http\UploadedFile; - -/** - * CustomFilesystemInterface - * - * Name for CustomFilesystemInterface - * - * @category HttpClient - * @package Client - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -interface CustomFilesystemInterface -{ - /** - * Write contents to a file. - * - * @param string $path - * @param string $contents - * @param array $options - * @return bool - */ - public function put(string $path, string $contents, array $options = []): bool; - - /** - * Store uploaded file with auto-generated filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file - * @param array $options - * @return string|false Return stored path or false on failure - */ - public function putFile(string $path, $file, array $options = []): string|false; - - /** - * Store uploaded file with custom filename. - * - * @param string $path Directory path - * @param File|UploadedFile $file - * @param string $name Custom filename - * @param array $options - * @return string|false Return stored path or false on failure - */ - public function putFileAs(string $path, $file, string $name, array $options = []): string|false; - - /** - * Get public URL for a file. - * - * @param string $path - * @return string - */ - public function url(string $path): string; - - /** - * Get temporary signed URL with expiration. - * - * @param string $path - * @param DateTimeInterface $expiration - * @param array $options - * @return string - */ - public function temporaryUrl(string $path, DateTimeInterface $expiration, array $options = []): string; - - /** - * Get all files in a directory recursively. - * - * @param string|null $directory - * @return array - */ - public function allFiles(?string $directory = null): array; - - /** - * Get all directories in a directory recursively. - * - * @param string|null $directory - * @return array - */ - public function allDirectories(?string $directory = null): array; -} \ No newline at end of file diff --git a/src/Libraries/Filesystem/CustomFilesystemManager.php b/src/Libraries/Filesystem/CustomFilesystemManager.php deleted file mode 100644 index 5792842..0000000 --- a/src/Libraries/Filesystem/CustomFilesystemManager.php +++ /dev/null @@ -1,256 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem; - -use InvalidArgumentException; -use Laravel\Lumen\Application; -use Spotlibs\PhpLib\Libraries\Filesystem\Adapters\MinioAdapter; -use Spotlibs\PhpLib\Libraries\Filesystem\Adapters\NfsAdapter; -use Spotlibs\PhpLib\Libraries\Filesystem\Contracts\CustomFilesystemInterface; - -/** - * CustomFilesystemManager - * - * Manager for creating and managing filesystem adapters - * - * @category Library - * @package Libraries - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class CustomFilesystemManager -{ - /** - * Application instance. - * - * @var Application - */ - protected $app; - - /** - * Resolved disk instances. - * - * @var array - */ - protected array $disks = []; - - /** - * Custom driver creators. - * - * @var array - */ - protected array $customCreators = []; - - /** - * Constructor. - * - * @param Application $app Application instance - */ - public function __construct($app) - { - $this->app = $app; - } - - /** - * Get a filesystem disk instance. - * - * @param string|null $name Disk name - * - * @return CustomFilesystemInterface - * - * @throws InvalidArgumentException - */ - public function disk(?string $name = null): CustomFilesystemInterface - { - $name = $name ?? $this->getDefaultDisk(); - - return $this->disks[$name] ??= $this->resolve($name); - } - - /** - * Resolve the given disk. - * - * @param string $name Disk name - * - * @return CustomFilesystemInterface - * - * @throws InvalidArgumentException - */ - protected function resolve(string $name): CustomFilesystemInterface - { - $config = $this->getConfig($name); - - if (empty($config)) { - throw new InvalidArgumentException("Disk [{$name}] is not configured."); - } - - $driver = $config['driver'] ?? null; - - if (empty($driver)) { - throw new InvalidArgumentException("Disk [{$name}] does not have a configured driver."); - } - - // Check for custom creator first - if (isset($this->customCreators[$driver])) { - return $this->callCustomCreator($driver, $config); - } - - // Use built-in drivers - $method = 'create' . ucfirst($driver) . 'Driver'; - - if (method_exists($this, $method)) { - return $this->{$method}($config); - } - - throw new InvalidArgumentException("Driver [{$driver}] is not supported."); - } - - /** - * Create NFS driver instance. - * - * @param array $config Configuration array - * - * @return NfsAdapter - */ - protected function createNfsDriver(array $config): NfsAdapter - { - return new NfsAdapter($config); - } - - /** - * Create MinIO driver instance. - * - * @param array $config Configuration array - * - * @return MinioAdapter - */ - protected function createMinioDriver(array $config): MinioAdapter - { - return new MinioAdapter($config); - } - - /** - * Call a custom driver creator. - * - * @param string $driver Driver name - * @param array $config Configuration array - * - * @return CustomFilesystemInterface - */ - protected function callCustomCreator(string $driver, array $config): CustomFilesystemInterface - { - return $this->customCreators[$driver]($this->app, $config); - } - - /** - * Register a custom driver creator. - * - * @param string $driver Driver name - * @param callable $callback Creator callback - * - * @return $this - */ - public function extend(string $driver, callable $callback): self - { - $this->customCreators[$driver] = $callback; - - return $this; - } - - /** - * Get the default disk name. - * - * @return string - */ - public function getDefaultDisk(): string - { - return $this->app['config']['custom-filesystems.default'] ?? 'nfs'; - } - - /** - * Set the default disk name. - * - * @param string $name Disk name - * - * @return void - */ - public function setDefaultDisk(string $name): void - { - $this->app['config']['custom-filesystems.default'] = $name; - } - - /** - * Get the configuration for a disk. - * - * @param string $name Disk name - * - * @return array - */ - protected function getConfig(string $name): array - { - return $this->app['config']["custom-filesystems.disks.{$name}"] ?? []; - } - - /** - * Forget a resolved disk instance. - * - * @param string $name Disk name - * - * @return $this - */ - public function forgetDisk(string $name): self - { - unset($this->disks[$name]); - - return $this; - } - - /** - * Forget all resolved disk instances. - * - * @return $this - */ - public function forgetAllDisks(): self - { - $this->disks = []; - - return $this; - } - - /** - * Get all resolved disk instances. - * - * @return array - */ - public function getDisks(): array - { - return $this->disks; - } - - /** - * Dynamically call the default disk instance. - * - * @param string $method Method name - * @param array $parameters Method parameters - * - * @return mixed - */ - public function __call(string $method, array $parameters) - { - return $this->disk()->$method(...$parameters); - } -} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php b/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php deleted file mode 100644 index 644069c..0000000 --- a/src/Libraries/Filesystem/Providers/CustomFilesystemServiceProvider.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem\Providers; - -use Illuminate\Support\ServiceProvider; -use Spotlibs\PhpLib\Libraries\Filesystem\CustomFilesystemManager; - -/** - * CustomFilesystemServiceProvider - * - * Service provider for registering CustomFilesystemManager - * - * @category Library - * @package Libraries - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -class CustomFilesystemServiceProvider extends ServiceProvider -{ - /** - * Register any application services. - * - * @return void - */ - public function register(): void - { - // Register CustomFilesystemManager as singleton - $this->app->singleton('custom-filesystem', function ($app) { - return new CustomFilesystemManager($app); - }); - - // Bind interface to manager for dependency injection - $this->app->singleton( - CustomFilesystemManager::class, - function ($app) { - return $app['custom-filesystem']; - } - ); - } - - /** - * Bootstrap any application services. - * - * @return void - */ - public function boot(): void - { - // Nothing to boot for Lumen - // Config is loaded manually in bootstrap/app.php - } - - /** - * Get the services provided by the provider. - * - * @return array - */ - public function provides(): array - { - return [ - 'custom-filesystem', - CustomFilesystemManager::class, - ]; - } -} \ No newline at end of file diff --git a/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php b/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php deleted file mode 100644 index b1b06f4..0000000 --- a/src/Libraries/Filesystem/Traits/NfsPermissionTrait.php +++ /dev/null @@ -1,196 +0,0 @@ - - * @license https://mit-license.org/ MIT License - * @version GIT: 0.3.7 - * @link https://github.com/spotlibs - */ - -declare(strict_types=1); - -namespace Spotlibs\PhpLib\Libraries\Filesystem\Traits; - -/** - * NfsPermissionTrait - * - * Name for NfsPermissionTrait - * - * @category HttpClient - * @package Client - * @author Mufthi Ryanda - * @license https://mit-license.org/ MIT License - * @link https://github.com/spotlibs - */ -trait NfsPermissionTrait -{ - /** - * Default owner for files/directories. - * - * @var string - */ - protected string $owner = 'www-data'; - - /** - * Default group for files/directories. - * - * @var string - */ - protected string $group = 'www-data'; - - /** - * Default file permission. - * - * @var int - */ - protected int $filePermission = 0644; - - /** - * Default directory permission. - * - * @var int - */ - protected int $directoryPermission = 0755; - - /** - * Set permission configuration from config array. - * - * @param array $config - * @return void - */ - protected function setPermissionConfig(array $config): void - { - $this->owner = $config['owner'] ?? 'www-data'; - $this->group = $config['group'] ?? 'www-data'; - $this->filePermission = $config['file_permission'] ?? 0644; - $this->directoryPermission = $config['directory_permission'] ?? 0755; - } - - /** - * Set ownership and permission for a file. - * - * @param string $path Full path to file - * @return bool - */ - protected function setFilePermission(string $path): bool - { - if (!file_exists($path)) { - return false; - } - - $this->changeMode($path, $this->filePermission); - $this->changeOwner($path); - - return true; - } - - /** - * Set ownership and permission for a directory. - * - * @param string $path Full path to directory - * @return bool - */ - protected function setDirectoryPermission(string $path): bool - { - if (!is_dir($path)) { - return false; - } - - $this->changeMode($path, $this->directoryPermission); - $this->changeOwner($path); - - return true; - } - - /** - * Change file/directory mode (chmod). - * - * @param string $path - * @param int $permission - * @return bool - */ - protected function changeMode(string $path, int $permission): bool - { - try { - return chmod($path, $permission); - } catch (\Throwable $e) { - return false; - } - } - - /** - * Change file/directory owner and group (chown & chgrp). - * - * @param string $path - * @return bool - */ - protected function changeOwner(string $path): bool - { - try { - chown($path, $this->owner); - chgrp($path, $this->group); - return true; - } catch (\Throwable $e) { - return false; - } - } - - /** - * Ensure directory exists, create if not. - * Also sets proper permission for all created directories. - * - * @param string $path Full path to directory - * @return bool - */ - protected function ensureDirectoryExists(string $path): bool - { - if (is_dir($path)) { - return true; - } - - try { - // Create directory recursively - mkdir($path, $this->directoryPermission, true); - - // Set permission for the created directory - $this->setDirectoryPermission($path); - - return true; - } catch (\Throwable $e) { - return false; - } - } - - /** - * Ensure directory exists and set permission for all parent directories. - * Useful when creating nested directories. - * - * @param string $basePath Base path (root) - * @param string $relativePath Relative path from base - * @return bool - */ - protected function ensureDirectoryExistsWithParents(string $basePath, string $relativePath): bool - { - $parts = array_filter(explode('/', $relativePath)); - $currentPath = rtrim($basePath, '/'); - - foreach ($parts as $part) { - $currentPath .= '/' . $part; - - if (!is_dir($currentPath)) { - try { - mkdir($currentPath, $this->directoryPermission); - $this->setDirectoryPermission($currentPath); - } catch (\Throwable $e) { - return false; - } - } - } - - return true; - } -} \ No newline at end of file diff --git a/src/Libraries/Storage.php b/src/Libraries/Storage.php new file mode 100644 index 0000000..31bfa25 --- /dev/null +++ b/src/Libraries/Storage.php @@ -0,0 +1,57 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.7.0 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries; + +use Spotlibs\PhpLib\Exceptions\RuntimeException; +use Spotlibs\PhpLib\Libraries\StorageDrivers\Minio; +use Spotlibs\PhpLib\Libraries\StorageDrivers\NFS; +use Spotlibs\PhpLib\Libraries\StorageDrivers\StorageInterface; + +/** + * Storage + * + * @category Library + * @package Libraries + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class Storage +{ + private static array $drivers = ['nfs', 'minio']; + private string $disk; + /** + * Create a new Storage instance for the specified driver. + * + * @param string $driver The storage driver to use. + * + * @throws RuntimeException + * + * @return Storage + */ + public static function disk(string $driver): StorageInterface + { + if (!in_array($driver, self::$drivers)) { + throw new RuntimeException("Invalid driver: $driver"); + } + + if ($driver === 'nfs') { + return new NFS(); + } + + return new Minio(); + } +} diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php new file mode 100644 index 0000000..9bde21b --- /dev/null +++ b/src/Libraries/StorageDrivers/Minio.php @@ -0,0 +1,109 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.7.0 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\StorageDrivers; + +use Carbon\Carbon; +use Illuminate\Http\File; +use Illuminate\Support\Facades\Storage; + +/** + * Storage + * + * @category Library + * @package Libraries + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class Minio implements StorageInterface +{ + /** + * Upload file to disk + * + * @param File $file file from http request + * @param string $dirpath where to put the file + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function upload(File $file, string $dirpath): bool + { + Storage::disk('minio')->put($dirpath, $file->getContent()); + return true; + } + /** + * Copy file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function copy(string $srcPath, string $destPath): bool + { + Storage::disk('minio')->copy($srcPath, $destPath); + return true; + } + /** + * Delete file in disk + * + * @param string $filepath file path to delete + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function delete(string $filepath): bool + { + Storage::disk('minio')->delete($filepath); + return true; + } + /** + * Move file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function move(string $srcPath, string $destPath): bool + { + Storage::disk('minio')->move($srcPath, $destPath); + return true; + } + /** + * Create temporary URL for file in disk + * + * @param string $filepath file path to create secure link + * + * @return string + */ + public function temporaryUrl(string $filepath): string + { + /** + * Illuminate\Filesystem\FilesystemAdapter $disk file storage disk + * + * @var \Illuminate\Filesystem\FilesystemAdapter $disk file storage disk + */ + $disk = Storage::disk('minio'); + return $disk->temporaryUrl($filepath, Carbon::now()->addSeconds(env('MINIO_EXPIRED_URL', 60))); + } +} diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php new file mode 100644 index 0000000..a826aa8 --- /dev/null +++ b/src/Libraries/StorageDrivers/NFS.php @@ -0,0 +1,154 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.7.0 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\StorageDrivers; + +use Illuminate\Http\File; +use Illuminate\Support\Str; +use Spotlibs\PhpLib\Exceptions\RuntimeException; +use Spotlibs\PhpLib\Logs\Log; + +/** + * Storage + * + * @category Library + * @package Libraries + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class NFS implements StorageInterface +{ + /** + * Upload file to disk + * + * @param File $file file from http request + * @param string $dirpath where to put the file + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function upload(File $file, string $dirpath): bool + { + if (!is_dir($dirpath)) { + if (!mkdir($dirpath, 0664, true)) { + throw new RuntimeException("Failed to create destination directory: $dirpath"); + } + } + $file->move($dirpath); + return true; + } + /** + * Copy file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function copy(string $srcPath, string $destPath): bool + { + if (!is_file($srcPath)) { + throw new RuntimeException("File not found within filepath: $srcPath"); + } + $tmp = explode("/", $destPath); + $destDir = implode("/", array_slice($tmp, 0, -1)); + if (!is_dir($destDir)) { + if (!mkdir($destDir, 0664, true)) { + throw new RuntimeException("Failed to create destination directory: $destDir"); + } + } + if (!exec("mv $srcPath $destPath")) { + throw new RuntimeException("Failed to move from $srcPath to $destPath"); + } + + return (bool) exec("chown -R 33:33 $destDir"); + } + /** + * Delete file in disk + * + * @param string $filepath file path to delete + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function delete(string $filepath): bool + { + if (!is_file($filepath)) { + return true; + } + if (!exec("rm $filepath")) { + throw new RuntimeException("Failed to delete $filepath"); + } + return true; + } + /** + * Move file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function move(string $srcPath, string $destPath): bool + { + $tmp = explode("/", $destPath); + $destDir = implode("/", array_slice($tmp, 0, -1)); + if (!is_dir($destDir)) { + if (!mkdir($destDir, 0664, true)) { + throw new RuntimeException("Failed to create destination directory: $destDir"); + } + } + if (!exec("mv $srcPath $destPath")) { + throw new RuntimeException("Failed to move from $srcPath to $destPath"); + } + + return (bool) exec("chown -R 33:33 $destDir"); + } + /** + * Create temporary URL for file in disk + * + * @param string $filepath file path to create secure link + * + * @return string + */ + public function temporaryUrl(string $filepath): string + { + if (!is_file($filepath)) { + Log::runtime()->warning( + [ + "message" => "File not found within filepath: $filepath" + ] + ); + return ""; + } + $random = Str::random(40); + if (!exec("ln -s $filepath /var/www/html/public/securelink/$random")) { + Log::runtime()->warning( + [ + "error" => "Failed to create secure link for file: $filepath", + ] + ); + return ""; + } + return env("APP_URL", "localhost:8080") . "/securelink/$random"; + } +} diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php new file mode 100644 index 0000000..fc27ec2 --- /dev/null +++ b/src/Libraries/StorageDrivers/StorageInterface.php @@ -0,0 +1,82 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.7.0 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\StorageDrivers; + +use Illuminate\Http\File; + +/** + * Storage + * + * @category Library + * @package Libraries + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +interface StorageInterface +{ + /** + * Upload file to disk + * + * @param File $file file from http request + * @param string $dirpath where to put the file + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function upload(File $file, string $dirpath): bool; + /** + * Copy file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function copy(string $srcPath, string $destPath): bool; + /** + * Delete file in disk + * + * @param string $filepath file path to delete + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function delete(string $filepath): bool; + /** + * Move file in disk + * + * @param string $srcPath source file path + * @param string $destPath destination file path + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return bool + */ + public function move(string $srcPath, string $destPath): bool; + /** + * Create temporary URL for file in disk + * + * @param string $filepath file path to create secure link + * + * @return void + */ + public function temporaryUrl(string $filepath): string; +} From 63473b53e513270eee8a9e52052ed6c50a554019 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Mon, 19 Jan 2026 17:37:33 +0700 Subject: [PATCH 15/42] ready to test --- src/Libraries/Storage.php | 40 +++++++++--- src/Libraries/StorageDrivers/Minio.php | 62 ++++++++++++++++--- src/Libraries/StorageDrivers/NFS.php | 61 +++++++++++++----- .../StorageDrivers/StorageInterface.php | 16 ++++- 4 files changed, 143 insertions(+), 36 deletions(-) diff --git a/src/Libraries/Storage.php b/src/Libraries/Storage.php index 31bfa25..6faaa6d 100644 --- a/src/Libraries/Storage.php +++ b/src/Libraries/Storage.php @@ -31,27 +31,47 @@ */ class Storage { - private static array $drivers = ['nfs', 'minio']; - private string $disk; + protected string $driver; /** * Create a new Storage instance for the specified driver. * * @param string $driver The storage driver to use. * - * @throws RuntimeException - * * @return Storage */ public static function disk(string $driver): StorageInterface { - if (!in_array($driver, self::$drivers)) { - throw new RuntimeException("Invalid driver: $driver"); + if (str_contains(strtolower($driver), "minio")) { + return new Minio($driver); } + return new NFS($driver); + } - if ($driver === 'nfs') { - return new NFS(); + /** + * Create a new Storage instance. + * + * @param string $driver driver name. example: nfs_xxx + * + * @return void + */ + public function __construct(string $driver) + { + $this->driver = $driver; + } + /** + * Parse file name from filepath + * + * @param string $filepath path of the file + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return string + */ + protected function getFileName(string $filepath): string + { + if ($x = explode("/", $filepath)) { + return $x[-1]; } - - return new Minio(); + throw new RuntimeException("failed to get filename from $filepath"); } } diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 9bde21b..78f7c20 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -17,7 +17,10 @@ use Carbon\Carbon; use Illuminate\Http\File; -use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Storage as FacadeStorage; +use Illuminate\Support\Str; +use Spotlibs\PhpLib\Exceptions\RuntimeException; +use Spotlibs\PhpLib\Libraries\Storage; /** * Storage @@ -28,8 +31,19 @@ * @license https://mit-license.org/ MIT License * @link https://github.com/spotlibs */ -class Minio implements StorageInterface +class Minio extends Storage implements StorageInterface { + /** + * Create a new NFS instance. + * + * @param string $driver driver name. example: minio_xxx + * + * @return void + */ + public function __construct(string $driver) + { + parent::__construct($driver); + } /** * Upload file to disk * @@ -42,7 +56,7 @@ class Minio implements StorageInterface */ public function upload(File $file, string $dirpath): bool { - Storage::disk('minio')->put($dirpath, $file->getContent()); + FacadeStorage::disk('minio')->put($dirpath, $file->getContent()); return true; } /** @@ -57,7 +71,7 @@ public function upload(File $file, string $dirpath): bool */ public function copy(string $srcPath, string $destPath): bool { - Storage::disk('minio')->copy($srcPath, $destPath); + FacadeStorage::disk('minio')->copy($srcPath, $destPath); return true; } /** @@ -71,7 +85,7 @@ public function copy(string $srcPath, string $destPath): bool */ public function delete(string $filepath): bool { - Storage::disk('minio')->delete($filepath); + FacadeStorage::disk('minio')->delete($filepath); return true; } /** @@ -86,24 +100,54 @@ public function delete(string $filepath): bool */ public function move(string $srcPath, string $destPath): bool { - Storage::disk('minio')->move($srcPath, $destPath); + FacadeStorage::disk('minio')->move($srcPath, $destPath); return true; } /** * Create temporary URL for file in disk * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * * @return string */ - public function temporaryUrl(string $filepath): string + public function securelink(string $hostname, string $filepath): string { /** * Illuminate\Filesystem\FilesystemAdapter $disk file storage disk * * @var \Illuminate\Filesystem\FilesystemAdapter $disk file storage disk */ - $disk = Storage::disk('minio'); - return $disk->temporaryUrl($filepath, Carbon::now()->addSeconds(env('MINIO_EXPIRED_URL', 60))); + $disk = FacadeStorage::disk('minio'); + $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds(env('MINIO_EXPIRED_URL', 60))); + return $hostname . "/" . $urlpath; + } + /** + * Create temporary URL for a folder in disk + * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com + * @param string $dirpath directory path to create secure link + * + * @return array + */ + public function securelinkFolder(string $hostname, string $dirpath): array + { + $random = Str::random(40); + $linkFolder = "/var/www/html/public/securelink/$random"; + if (!exec("mkdir $linkFolder")) { + throw new RuntimeException("Failed to create securelink directory: $linkFolder"); + } + $allFiles = FacadeStorage::disk(parent::$driver)->allFiles($dirpath); + $result = []; + foreach ($allFiles as $file) { + $filename = parent::getFileName($file); + $fileStream = FacadeStorage::disk(parent::$driver)->readStream($file); + $writeStream = fopen($linkFolder . "/" . $filename, 'w'); + stream_copy_to_stream($fileStream, $writeStream); + fclose($fileStream); + fclose($writeStream); + $result[] = $hostname . "/securelink/" . $linkFolder . "/" . $filename; + } + return $result; } } diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index a826aa8..1e2e18f 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -18,7 +18,7 @@ use Illuminate\Http\File; use Illuminate\Support\Str; use Spotlibs\PhpLib\Exceptions\RuntimeException; -use Spotlibs\PhpLib\Logs\Log; +use Spotlibs\PhpLib\Libraries\Storage; /** * Storage @@ -29,8 +29,19 @@ * @license https://mit-license.org/ MIT License * @link https://github.com/spotlibs */ -class NFS implements StorageInterface +class NFS extends Storage implements StorageInterface { + /** + * Create a new NFS instance. + * + * @param string $driver driver name. example: nfs_xxx + * + * @return void + */ + public function __construct(string $driver) + { + parent::__construct($driver); + } /** * Upload file to disk * @@ -126,29 +137,47 @@ public function move(string $srcPath, string $destPath): bool /** * Create temporary URL for file in disk * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * * @return string */ - public function temporaryUrl(string $filepath): string + public function securelink(string $hostname, string $filepath): string { if (!is_file($filepath)) { - Log::runtime()->warning( - [ - "message" => "File not found within filepath: $filepath" - ] - ); - return ""; + throw new RuntimeException("File not found within filepath: $filepath"); } $random = Str::random(40); if (!exec("ln -s $filepath /var/www/html/public/securelink/$random")) { - Log::runtime()->warning( - [ - "error" => "Failed to create secure link for file: $filepath", - ] - ); - return ""; + throw new RuntimeException("Failed to create secure link for file: $filepath"); + } + return $hostname . "/securelink/$random"; + } + /** + * Create temporary URL for a folder in disk + * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com + * @param string $dirpath directory path to create secure link + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return array + */ + public function securelinkFolder(string $hostname, string $dirpath): array + { + if (!is_dir($dirpath)) { + throw new RuntimeException("Directory not found within dirpath: $dirpath"); + } + $random = Str::random(40); + if (!exec("ln -sf $dirpath /var/www/html/public/securelink/$random")) { + throw new RuntimeException("Failed to create secure link for file: $dirpath"); + } + $result = glob("/var/www/html/public/securelink/$random/*"); + foreach ($result as $key => $r) { + $result[$key] = str_replace("/var/www/html", $hostname, $r); } - return env("APP_URL", "localhost:8080") . "/securelink/$random"; + return $result; } } diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php index fc27ec2..84b9b83 100644 --- a/src/Libraries/StorageDrivers/StorageInterface.php +++ b/src/Libraries/StorageDrivers/StorageInterface.php @@ -74,9 +74,23 @@ public function move(string $srcPath, string $destPath): bool; /** * Create temporary URL for file in disk * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * * @return void */ - public function temporaryUrl(string $filepath): string; + public function securelink(string $hostname, string $filepath): string; + /** + * Create temporary URL for a folder in disk + * + * @param string $hostname host name which client can access. example: https://my-api-gateway.com + * @param string $dirpath directory path to create secure link + * + * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException + * + * @return array + */ + public function securelinkFolder(string $hostname, string $dirpath): array; } From e42a2527bf86cf619e16415d3e98e9c4b87b50ff Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Mon, 19 Jan 2026 18:43:20 +0700 Subject: [PATCH 16/42] replace storage extension --- src/Libraries/Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/Storage.php b/src/Libraries/Storage.php index 6faaa6d..7f98128 100644 --- a/src/Libraries/Storage.php +++ b/src/Libraries/Storage.php @@ -37,7 +37,7 @@ class Storage * * @param string $driver The storage driver to use. * - * @return Storage + * @return \Spotlibs\PhpLib\Libraries\StorageDrivers\StorageInterface */ public static function disk(string $driver): StorageInterface { From ff8817fb37fd2a6bc3a5841bd53eceafb32b0899 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Mon, 19 Jan 2026 19:03:46 +0700 Subject: [PATCH 17/42] fix missing filename after dirpath --- src/Libraries/StorageDrivers/Minio.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 78f7c20..8d16251 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -56,7 +56,7 @@ public function __construct(string $driver) */ public function upload(File $file, string $dirpath): bool { - FacadeStorage::disk('minio')->put($dirpath, $file->getContent()); + FacadeStorage::disk('minio')->put($dirpath . "/" . $file->getFilename(), $file->getContent()); return true; } /** From aa05a5f863a85c810cb25b5948a4350db3adf892 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 21 Jan 2026 12:04:25 +0700 Subject: [PATCH 18/42] change to uploaded file instead --- src/Libraries/StorageDrivers/Minio.php | 8 ++++---- src/Libraries/StorageDrivers/NFS.php | 8 ++++---- src/Libraries/StorageDrivers/StorageInterface.php | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 8d16251..ec1aede 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -16,7 +16,7 @@ namespace Spotlibs\PhpLib\Libraries\StorageDrivers; use Carbon\Carbon; -use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage as FacadeStorage; use Illuminate\Support\Str; use Spotlibs\PhpLib\Exceptions\RuntimeException; @@ -47,14 +47,14 @@ public function __construct(string $driver) /** * Upload file to disk * - * @param File $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(File $file, string $dirpath): bool + public function upload(UploadedFile $file, string $dirpath): bool { FacadeStorage::disk('minio')->put($dirpath . "/" . $file->getFilename(), $file->getContent()); return true; diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index 1e2e18f..9c891b1 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -15,7 +15,7 @@ namespace Spotlibs\PhpLib\Libraries\StorageDrivers; -use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; use Illuminate\Support\Str; use Spotlibs\PhpLib\Exceptions\RuntimeException; use Spotlibs\PhpLib\Libraries\Storage; @@ -45,14 +45,14 @@ public function __construct(string $driver) /** * Upload file to disk * - * @param File $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(File $file, string $dirpath): bool + public function upload(UploadedFile $file, string $dirpath): bool { if (!is_dir($dirpath)) { if (!mkdir($dirpath, 0664, true)) { diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php index 84b9b83..9fadf78 100644 --- a/src/Libraries/StorageDrivers/StorageInterface.php +++ b/src/Libraries/StorageDrivers/StorageInterface.php @@ -15,7 +15,7 @@ namespace Spotlibs\PhpLib\Libraries\StorageDrivers; -use Illuminate\Http\File; +use Illuminate\Http\UploadedFile; /** * Storage @@ -31,14 +31,14 @@ interface StorageInterface /** * Upload file to disk * - * @param File $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(File $file, string $dirpath): bool; + public function upload(UploadedFile $file, string $dirpath): bool; /** * Copy file in disk * From 4bcf5b6db011346c9b3deaf1e14b5dd9979dc39a Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 21 Jan 2026 12:11:19 +0700 Subject: [PATCH 19/42] change to uploaded file instead --- src/Libraries/StorageDrivers/Minio.php | 2 +- src/Libraries/StorageDrivers/NFS.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index ec1aede..6c36d4b 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -56,7 +56,7 @@ public function __construct(string $driver) */ public function upload(UploadedFile $file, string $dirpath): bool { - FacadeStorage::disk('minio')->put($dirpath . "/" . $file->getFilename(), $file->getContent()); + FacadeStorage::disk('minio')->put($dirpath . "/" . $file->getClientOriginalName(), $file->getContent()); return true; } /** diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index 9c891b1..cc1c37c 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -59,7 +59,7 @@ public function upload(UploadedFile $file, string $dirpath): bool throw new RuntimeException("Failed to create destination directory: $dirpath"); } } - $file->move($dirpath); + $file->move($dirpath, $file->getClientOriginalName()); return true; } /** From 95f605b93ab0e57c4ebecb5ef5b0c31a69547d01 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 21 Jan 2026 12:22:39 +0700 Subject: [PATCH 20/42] change to uploaded file instead --- src/Libraries/StorageDrivers/Minio.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 6c36d4b..d0cc0a9 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -119,7 +119,7 @@ public function securelink(string $hostname, string $filepath): string * @var \Illuminate\Filesystem\FilesystemAdapter $disk file storage disk */ $disk = FacadeStorage::disk('minio'); - $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds(env('MINIO_EXPIRED_URL', 60))); + $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds((int) env('MINIO_EXPIRED_URL', 60))); return $hostname . "/" . $urlpath; } /** From 57b383bfef2dd731560bc44cf21c94b4fa854576 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 21 Jan 2026 13:22:26 +0700 Subject: [PATCH 21/42] remove hostname as param --- src/Libraries/StorageDrivers/Minio.php | 12 +++++------- src/Libraries/StorageDrivers/NFS.php | 12 +++++------- src/Libraries/StorageDrivers/StorageInterface.php | 8 +++----- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index d0cc0a9..0715274 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -106,12 +106,11 @@ public function move(string $srcPath, string $destPath): bool /** * Create temporary URL for file in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * * @return string */ - public function securelink(string $hostname, string $filepath): string + public function securelink(string $filepath): string { /** * Illuminate\Filesystem\FilesystemAdapter $disk file storage disk @@ -120,17 +119,16 @@ public function securelink(string $hostname, string $filepath): string */ $disk = FacadeStorage::disk('minio'); $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds((int) env('MINIO_EXPIRED_URL', 60))); - return $hostname . "/" . $urlpath; + return $urlpath; } /** * Create temporary URL for a folder in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com - * @param string $dirpath directory path to create secure link + * @param string $dirpath directory path to create secure link * * @return array */ - public function securelinkFolder(string $hostname, string $dirpath): array + public function securelinkFolder(string $dirpath): array { $random = Str::random(40); $linkFolder = "/var/www/html/public/securelink/$random"; @@ -146,7 +144,7 @@ public function securelinkFolder(string $hostname, string $dirpath): array stream_copy_to_stream($fileStream, $writeStream); fclose($fileStream); fclose($writeStream); - $result[] = $hostname . "/securelink/" . $linkFolder . "/" . $filename; + $result[] = env('APP_URL') . "/securelink/" . $linkFolder . "/" . $filename; } return $result; } diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index cc1c37c..4a175b2 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -137,14 +137,13 @@ public function move(string $srcPath, string $destPath): bool /** * Create temporary URL for file in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return string */ - public function securelink(string $hostname, string $filepath): string + public function securelink(string $filepath): string { if (!is_file($filepath)) { throw new RuntimeException("File not found within filepath: $filepath"); @@ -153,19 +152,18 @@ public function securelink(string $hostname, string $filepath): string if (!exec("ln -s $filepath /var/www/html/public/securelink/$random")) { throw new RuntimeException("Failed to create secure link for file: $filepath"); } - return $hostname . "/securelink/$random"; + return env('APP_URL') . "/securelink/$random"; } /** * Create temporary URL for a folder in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com - * @param string $dirpath directory path to create secure link + * @param string $dirpath directory path to create secure link * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return array */ - public function securelinkFolder(string $hostname, string $dirpath): array + public function securelinkFolder(string $dirpath): array { if (!is_dir($dirpath)) { throw new RuntimeException("Directory not found within dirpath: $dirpath"); @@ -176,7 +174,7 @@ public function securelinkFolder(string $hostname, string $dirpath): array } $result = glob("/var/www/html/public/securelink/$random/*"); foreach ($result as $key => $r) { - $result[$key] = str_replace("/var/www/html", $hostname, $r); + $result[$key] = str_replace("/var/www/html", env('APP_URL'), $r); } return $result; } diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php index 9fadf78..6dcff3d 100644 --- a/src/Libraries/StorageDrivers/StorageInterface.php +++ b/src/Libraries/StorageDrivers/StorageInterface.php @@ -74,23 +74,21 @@ public function move(string $srcPath, string $destPath): bool; /** * Create temporary URL for file in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com * @param string $filepath file path to create secure link * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return void */ - public function securelink(string $hostname, string $filepath): string; + public function securelink(string $filepath): string; /** * Create temporary URL for a folder in disk * - * @param string $hostname host name which client can access. example: https://my-api-gateway.com - * @param string $dirpath directory path to create secure link + * @param string $dirpath directory path to create secure link * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return array */ - public function securelinkFolder(string $hostname, string $dirpath): array; + public function securelinkFolder(string $dirpath): array; } From 10fb571db4c11fe6467588e41f3c364fc1a454cf Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 21 Jan 2026 15:06:06 +0700 Subject: [PATCH 22/42] custom minio fs adapter --- composer.json | 3 +- composer.lock | 1798 +++++++++++------ src/Libraries/StorageDrivers/MinioAdapter.php | 101 + 3 files changed, 1270 insertions(+), 632 deletions(-) create mode 100644 src/Libraries/StorageDrivers/MinioAdapter.php diff --git a/composer.json b/composer.json index fa5e7cf..8040873 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "php": "^8.3", "laravel/lumen-framework": "^11.2.0", "jobcloud/php-kafka-lib": "~2.0.0", - "flix-tech/avro-serde-php": "~2.1.0" + "flix-tech/avro-serde-php": "~2.1.0", + "league/flysystem-aws-s3-v3": "^3.30" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 4d1923e..b7a323a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b3565164e12460c5423e66de9634abfe", + "content-hash": "af43f19ec25ba2e225249956d25ef57f", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.337.3", + "version": "3.369.16", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6" + "reference": "f7ae10a0b691d40075c801e3ae8735a722debfac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/06dfc8f76423b49aaa181debd25bbdc724c346d6", - "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f7ae10a0b691d40075c801e3ae8735a722debfac", + "reference": "f7ae10a0b691d40075c801e3ae8735a722debfac", "shasum": "" }, "require": { @@ -79,37 +79,36 @@ "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", - "guzzlehttp/promises": "^1.4.0 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", - "mtdowling/jmespath.php": "^2.6", - "php": ">=7.2.5", - "psr/http-message": "^1.0 || ^2.0" + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/promises": "^2.0", + "guzzlehttp/psr7": "^2.4.5", + "mtdowling/jmespath.php": "^2.8.0", + "php": ">=8.1", + "psr/http-message": "^1.0 || ^2.0", + "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", - "composer/composer": "^1.10.22", + "composer/composer": "^2.7.8", "dms/phpunit-arraysubset-asserts": "^0.4.0", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", - "ext-pcntl": "*", "ext-sockets": "*", - "nette/neon": "^2.3", - "paragonie/random_compat": ">= 2", - "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", - "sebastian/comparator": "^1.2.3 || ^4.0", - "yoast/phpunit-polyfills": "^1.0" + "phpunit/phpunit": "^9.6", + "psr/cache": "^2.0 || ^3.0", + "psr/simple-cache": "^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", + "yoast/phpunit-polyfills": "^2.0" }, "suggest": { "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", "doctrine/cache": "To use the DoctrineCacheAdapter", "ext-curl": "To send requests using cURL", "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-pcntl": "To use client-side monitoring", "ext-sockets": "To use client-side monitoring" }, "type": "library", @@ -152,11 +151,11 @@ "sdk" ], "support": { - "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.337.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.16" }, - "time": "2025-01-21T19:10:05+00:00" + "time": "2026-01-20T19:44:30+00:00" }, { "name": "beberlei/assert", @@ -227,25 +226,25 @@ }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "6.8.8" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -275,7 +274,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -283,7 +282,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -356,33 +355,32 @@ }, { "name": "doctrine/inflector", - "version": "2.0.10", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -427,7 +425,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -443,7 +441,7 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/lexer", @@ -524,29 +522,28 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" + "php": "^8.2|^8.3|^8.4|^8.5" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.32|^2.1.31", + "phpunit/phpunit": "^8.5.48|^9.0" }, "type": "library", "extra": { @@ -577,7 +574,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" }, "funding": [ { @@ -585,7 +582,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2025-10-31T18:51:33+00:00" }, { "name": "egulias/email-validator", @@ -843,31 +840,31 @@ }, { "name": "fruitcake/php-cors", - "version": "v1.3.0", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6|^7" + "php": "^8.1", + "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" }, "require-dev": { - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -898,7 +895,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" }, "funding": [ { @@ -910,7 +907,7 @@ "type": "github" } ], - "time": "2023-10-12T05:21:21+00:00" + "time": "2025-12-03T09:33:47+00:00" }, { "name": "functional-php/fantasy-land", @@ -962,24 +959,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.3", + "version": "v1.1.4", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3" + "phpoption/phpoption": "^1.9.5" }, "require-dev": { - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" }, "type": "library", "autoload": { @@ -1008,7 +1005,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" }, "funding": [ { @@ -1020,26 +1017,26 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:45:45+00:00" + "time": "2025-12-27T19:43:20+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.9.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1130,7 +1127,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -1146,20 +1143,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:37:11+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -1167,7 +1164,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -1213,7 +1210,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.2.0" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -1229,20 +1226,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:27:01+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -1258,7 +1255,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1329,7 +1326,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -1345,20 +1342,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.4", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { @@ -1367,7 +1364,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", "uri-template/tests": "1.0.0" }, "type": "library", @@ -1415,7 +1412,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" }, "funding": [ { @@ -1431,20 +1428,20 @@ "type": "tidelift" } ], - "time": "2025-02-03T10:55:03+00:00" + "time": "2025-08-22T14:27:06+00:00" }, { "name": "illuminate/auth", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/auth.git", - "reference": "da681d377fcd145ff61d82d809e5986b03226e75" + "reference": "474944fb7cc40942db14cb70db88eab810c46426" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/auth/zipball/da681d377fcd145ff61d82d809e5986b03226e75", - "reference": "da681d377fcd145ff61d82d809e5986b03226e75", + "url": "https://api.github.com/repos/illuminate/auth/zipball/474944fb7cc40942db14cb70db88eab810c46426", + "reference": "474944fb7cc40942db14cb70db88eab810c46426", "shasum": "" }, "require": { @@ -1489,11 +1486,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-05-11T20:46:35+00:00" }, { "name": "illuminate/broadcasting", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/broadcasting.git", @@ -1551,16 +1548,16 @@ }, { "name": "illuminate/bus", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/bus.git", - "reference": "5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3" + "reference": "2adf211bada7184410501b37882845230d6bf2f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/bus/zipball/5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3", - "reference": "5f7cd1f99b2ff7dd0ef20aead81da1390c4bc8e3", + "url": "https://api.github.com/repos/illuminate/bus/zipball/2adf211bada7184410501b37882845230d6bf2f4", + "reference": "2adf211bada7184410501b37882845230d6bf2f4", "shasum": "" }, "require": { @@ -1600,11 +1597,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-10-14T19:59:30+00:00" }, { "name": "illuminate/cache", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/cache.git", @@ -1666,7 +1663,7 @@ }, { "name": "illuminate/collections", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", @@ -1722,7 +1719,7 @@ }, { "name": "illuminate/conditionable", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -1768,7 +1765,7 @@ }, { "name": "illuminate/config", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", @@ -1816,16 +1813,16 @@ }, { "name": "illuminate/console", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/console.git", - "reference": "b60225f4f8aa52b015300b581436627e71ce1b18" + "reference": "a41fbfc99bac948ee27fc8d99bb0e5b4175dec00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/console/zipball/b60225f4f8aa52b015300b581436627e71ce1b18", - "reference": "b60225f4f8aa52b015300b581436627e71ce1b18", + "url": "https://api.github.com/repos/illuminate/console/zipball/a41fbfc99bac948ee27fc8d99bb0e5b4175dec00", + "reference": "a41fbfc99bac948ee27fc8d99bb0e5b4175dec00", "shasum": "" }, "require": { @@ -1878,11 +1875,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-11-11T13:49:37+00:00" }, { "name": "illuminate/container", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", @@ -1933,16 +1930,16 @@ }, { "name": "illuminate/contracts", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "4b2a67d1663f50085bc91e6371492697a5d2d4e8" + "reference": "4787042340aae19a7ea0fa82f4073c4826204a48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/4b2a67d1663f50085bc91e6371492697a5d2d4e8", - "reference": "4b2a67d1663f50085bc91e6371492697a5d2d4e8", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/4787042340aae19a7ea0fa82f4073c4826204a48", + "reference": "4787042340aae19a7ea0fa82f4073c4826204a48", "shasum": "" }, "require": { @@ -1977,24 +1974,24 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-11-27T16:16:07+00:00" }, { "name": "illuminate/database", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2" + "reference": "96abcce13f405701363d916dd312835e04848d04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2", - "reference": "0b3a1d429fb44c8bc2ed6afcc431872cbf3a85b2", + "url": "https://api.github.com/repos/illuminate/database/zipball/96abcce13f405701363d916dd312835e04848d04", + "reference": "96abcce13f405701363d916dd312835e04848d04", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", "ext-pdo": "*", "illuminate/collections": "^11.0", "illuminate/container": "^11.0", @@ -2046,11 +2043,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-09-29T09:23:31+00:00" }, { "name": "illuminate/encryption", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/encryption.git", @@ -2101,7 +2098,7 @@ }, { "name": "illuminate/events", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", @@ -2156,7 +2153,7 @@ }, { "name": "illuminate/filesystem", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", @@ -2223,7 +2220,7 @@ }, { "name": "illuminate/hashing", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/hashing.git", @@ -2271,16 +2268,16 @@ }, { "name": "illuminate/http", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/http.git", - "reference": "383df4e480dbd6272cc0d87fc8206b6405b1b9d8" + "reference": "b2c744c2dedc1d39b3d5ea6b85232de086f84351" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/http/zipball/383df4e480dbd6272cc0d87fc8206b6405b1b9d8", - "reference": "383df4e480dbd6272cc0d87fc8206b6405b1b9d8", + "url": "https://api.github.com/repos/illuminate/http/zipball/b2c744c2dedc1d39b3d5ea6b85232de086f84351", + "reference": "b2c744c2dedc1d39b3d5ea6b85232de086f84351", "shasum": "" }, "require": { @@ -2328,11 +2325,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:58:51+00:00" + "time": "2025-11-17T22:04:40+00:00" }, { "name": "illuminate/log", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/log.git", @@ -2385,7 +2382,7 @@ }, { "name": "illuminate/macroable", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -2431,7 +2428,7 @@ }, { "name": "illuminate/pagination", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/pagination.git", @@ -2481,7 +2478,7 @@ }, { "name": "illuminate/pipeline", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/pipeline.git", @@ -2529,16 +2526,16 @@ }, { "name": "illuminate/queue", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/queue.git", - "reference": "55b305a48a1325f30e2e23f879f5a7e7ee8b54cf" + "reference": "99218fcdd5efdc0e2c306d4585eb46d9181cf2da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/queue/zipball/55b305a48a1325f30e2e23f879f5a7e7ee8b54cf", - "reference": "55b305a48a1325f30e2e23f879f5a7e7ee8b54cf", + "url": "https://api.github.com/repos/illuminate/queue/zipball/99218fcdd5efdc0e2c306d4585eb46d9181cf2da", + "reference": "99218fcdd5efdc0e2c306d4585eb46d9181cf2da", "shasum": "" }, "require": { @@ -2592,11 +2589,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-07-01T15:36:47+00:00" }, { "name": "illuminate/session", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/session.git", @@ -2653,16 +2650,16 @@ }, { "name": "illuminate/support", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "915efb197e615dc8adf52fa96d02b9035ff9ce6f" + "reference": "20fbd9f9f502a55de0cbba3f3f81444b7c44af4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/915efb197e615dc8adf52fa96d02b9035ff9ce6f", - "reference": "915efb197e615dc8adf52fa96d02b9035ff9ce6f", + "url": "https://api.github.com/repos/illuminate/support/zipball/20fbd9f9f502a55de0cbba3f3f81444b7c44af4b", + "reference": "20fbd9f9f502a55de0cbba3f3f81444b7c44af4b", "shasum": "" }, "require": { @@ -2687,7 +2684,7 @@ "suggest": { "illuminate/filesystem": "Required to use the Composer class (^11.0).", "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", - "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.6).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).", "league/uri": "Required to use the Uri class (^7.5.1).", "ramsey/uuid": "Required to use Str::uuid() (^4.7).", "symfony/process": "Required to use the Composer class (^7.0).", @@ -2726,20 +2723,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-04-25T08:31:51+00:00" + "time": "2025-11-27T16:16:32+00:00" }, { "name": "illuminate/testing", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/testing.git", - "reference": "a9b9b829f597e5d085ff359b7e367a82bc71276c" + "reference": "cd8b8c5c938be790955a97147b2d999728dcd8bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/testing/zipball/a9b9b829f597e5d085ff359b7e367a82bc71276c", - "reference": "a9b9b829f597e5d085ff359b7e367a82bc71276c", + "url": "https://api.github.com/repos/illuminate/testing/zipball/cd8b8c5c938be790955a97147b2d999728dcd8bc", + "reference": "cd8b8c5c938be790955a97147b2d999728dcd8bc", "shasum": "" }, "require": { @@ -2785,11 +2782,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-09-01T02:19:50+00:00" }, { "name": "illuminate/translation", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/translation.git", @@ -2840,20 +2837,20 @@ }, { "name": "illuminate/validation", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/validation.git", - "reference": "fd6a85a4c5cad1a6f84b94aebaec71ea996307b0" + "reference": "076ebfb5fb60ab862588220688bdce3103287466" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/validation/zipball/fd6a85a4c5cad1a6f84b94aebaec71ea996307b0", - "reference": "fd6a85a4c5cad1a6f84b94aebaec71ea996307b0", + "url": "https://api.github.com/repos/illuminate/validation/zipball/076ebfb5fb60ab862588220688bdce3103287466", + "reference": "076ebfb5fb60ab862588220688bdce3103287466", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", "egulias/email-validator": "^3.2.5|^4.0", "ext-filter": "*", "ext-mbstring": "*", @@ -2897,11 +2894,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2025-09-02T23:55:36+00:00" }, { "name": "illuminate/view", - "version": "v11.44.7", + "version": "v11.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/view.git", @@ -3121,16 +3118,16 @@ }, { "name": "laravel/prompts", - "version": "v0.3.5", + "version": "v0.3.10", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" + "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", - "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", + "url": "https://api.github.com/repos/laravel/prompts/zipball/360ba095ef9f51017473505191fbd4ab73e1cab3", + "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3", "shasum": "" }, "require": { @@ -3146,9 +3143,9 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" + "pestphp/pest": "^2.3|^3.4|^4.0", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -3174,22 +3171,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.5" + "source": "https://github.com/laravel/prompts/tree/v0.3.10" }, - "time": "2025-02-11T13:34:40+00:00" + "time": "2026-01-13T20:29:29+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.4", + "version": "v2.0.8", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b", + "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b", "shasum": "" }, "require": { @@ -3198,7 +3195,7 @@ "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -3237,20 +3234,263 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-03-19T13:51:03+00:00" + "time": "2026-01-08T16:22:46+00:00" + }, + { + "name": "league/flysystem", + "version": "3.30.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", + "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.2" + }, + "time": "2025-11-10T17:13:11+00:00" + }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "3.30.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "d286e896083bed3190574b8b088b557b59eb66f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/d286e896083bed3190574b8b088b557b59eb66f5", + "reference": "d286e896083bed3190574b8b088b557b59eb66f5", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.295.10", + "league/flysystem": "^3.10.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3V3\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "AWS S3 filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "aws", + "file", + "files", + "filesystem", + "s3", + "storage" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.30.1" + }, + "time": "2025-10-20T15:27:33+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.30.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ab4f9d0d672f601b102936aa728801dd1a11968d", + "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.2" + }, + "time": "2025-11-10T11:23:37+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" }, { "name": "monolog/monolog", - "version": "3.9.0", + "version": "3.10.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", "shasum": "" }, "require": { @@ -3268,7 +3508,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", + "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -3328,7 +3568,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" }, "funding": [ { @@ -3340,20 +3580,86 @@ "type": "tidelift" } ], - "time": "2025-03-24T10:02:05+00:00" + "time": "2026-01-02T08:56:05+00:00" + }, + { + "name": "mtdowling/jmespath.php", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + }, + "time": "2024-09-04T18:46:31+00:00" }, { "name": "nesbot/carbon", - "version": "3.9.1", + "version": "3.11.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "ced71f79398ece168e24f7f7710462f462310d4d" + "reference": "bdb375400dcd162624531666db4799b36b64e4a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", - "reference": "ced71f79398ece168e24f7f7710462f462310d4d", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", + "reference": "bdb375400dcd162624531666db4799b36b64e4a1", "shasum": "" }, "require": { @@ -3361,9 +3667,9 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3 || ^7.0", + "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -3371,14 +3677,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.57.2", + "friendsofphp/php-cs-fixer": "^v3.87.1", "kylekatarnls/multi-tester": "^2.5.3", - "ondrejmirtes/better-reflection": "^6.25.0.4", "phpmd/phpmd": "^2.15.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.11.2", - "phpunit/phpunit": "^10.5.20", - "squizlabs/php_codesniffer": "^3.9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4" }, "bin": [ "bin/carbon" @@ -3446,7 +3751,7 @@ "type": "tidelift" } ], - "time": "2025-05-01T19:51:51+00:00" + "time": "2025-12-02T21:04:28+00:00" }, { "name": "nikic/fast-route", @@ -3500,31 +3805,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.3.1", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.2.6" + "symfony/console": "^7.3.6" }, "require-dev": { - "illuminate/console": "^11.44.7", - "laravel/pint": "^1.22.0", + "illuminate/console": "^11.46.1", + "laravel/pint": "^1.25.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.2", - "phpstan/phpstan": "^1.12.25", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.2.6", + "symfony/var-dumper": "^7.3.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -3567,7 +3872,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" }, "funding": [ { @@ -3583,20 +3888,20 @@ "type": "github" } ], - "time": "2025-05-08T08:14:37+00:00" + "time": "2025-11-20T02:34:59+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", "shasum": "" }, "require": { @@ -3604,7 +3909,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" }, "type": "library", "extra": { @@ -3646,7 +3951,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" }, "funding": [ { @@ -3658,7 +3963,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" + "time": "2025-12-27T19:41:33+00:00" }, { "name": "psr/clock", @@ -4194,21 +4499,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.9.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "8429c78ca35a09f27565311b98101e2826affde0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", + "reference": "8429c78ca35a09f27565311b98101e2826affde0", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", - "ext-json": "*", + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -4216,26 +4520,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -4270,32 +4571,22 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.9.2" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2025-12-14T04:43:48+00:00" }, { "name": "symfony/clock", - "version": "v7.2.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", + "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", "shasum": "" }, "require": { @@ -4340,7 +4631,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" + "source": "https://github.com/symfony/clock/tree/v7.4.0" }, "funding": [ { @@ -4351,32 +4642,37 @@ "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": "2024-09-25T14:21:43+00:00" + "time": "2025-11-12T15:39:26+00:00" }, { "name": "symfony/console", - "version": "v7.2.6", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" + "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -4390,16 +4686,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4433,7 +4729,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.6" + "source": "https://github.com/symfony/console/tree/v7.4.3" }, "funding": [ { @@ -4444,25 +4740,29 @@ "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-04-07T19:09:28+00:00" + "time": "2025-12-23T14:50:43+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -4475,7 +4775,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -4500,7 +4800,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -4516,35 +4816,38 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/error-handler", - "version": "v7.2.5", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4575,7 +4878,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.5" + "source": "https://github.com/symfony/error-handler/tree/v7.4.0" }, "funding": [ { @@ -4586,25 +4889,29 @@ "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-03-03T07:12:39+00:00" + "time": "2025-11-05T14:29:59+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d", + "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d", "shasum": "" }, "require": { @@ -4621,13 +4928,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4655,7 +4963,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.0" }, "funding": [ { @@ -4666,25 +4974,29 @@ "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": "2024-09-25T14:21:43+00:00" + "time": "2025-10-28T09:38:46+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -4698,7 +5010,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -4731,7 +5043,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -4747,32 +5059,34 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { - "name": "symfony/finder", - "version": "v7.2.2", + "name": "symfony/filesystem", + "version": "v7.4.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "url": "https://github.com/symfony/filesystem.git", + "reference": "d551b38811096d0be9c4691d406991b47c0c630a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", + "reference": "d551b38811096d0be9c4691d406991b47c0c630a", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/process": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -4792,10 +5106,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Finds files and directories via an intuitive fluent interface", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/filesystem/tree/v7.4.0" }, "funding": [ { @@ -4806,32 +5120,103 @@ "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": "2024-12-30T19:00:17+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { - "name": "symfony/http-foundation", - "version": "v7.2.6", + "name": "symfony/finder", + "version": "v7.4.3", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "6023ec7607254c87c5e69fb3558255aca440d72b" + "url": "https://github.com/symfony/finder.git", + "reference": "fffe05569336549b20a1be64250b40516d6e8d06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b", - "reference": "6023ec7607254c87c5e69fb3558255aca440d72b", + "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", + "reference": "fffe05569336549b20a1be64250b40516d6e8d06", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.4.3" + }, + "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-12-23T14:50:43+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52", + "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { "doctrine/dbal": "<3.6", @@ -4840,12 +5225,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^6.4.12|^7.1.5|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4873,7 +5259,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.3" }, "funding": [ { @@ -4884,34 +5270,38 @@ "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-04-09T08:14:01+00:00" + "time": "2025-12-23T14:23:49+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.6", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec" + "reference": "885211d4bed3f857b8c964011923528a55702aa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec", - "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5", + "reference": "885211d4bed3f857b8c964011923528a55702aa5", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -4921,6 +5311,7 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", + "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -4938,27 +5329,27 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^7.1|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.1|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "type": "library", @@ -4987,7 +5378,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.6" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.3" }, "funding": [ { @@ -4998,29 +5389,34 @@ "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-05-02T09:04:03+00:00" + "time": "2025-12-31T08:43:57+00:00" }, { "name": "symfony/mime", - "version": "v7.2.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1" + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1", - "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1", + "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -5035,11 +5431,11 @@ "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0" }, "type": "library", "autoload": { @@ -5071,7 +5467,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.6" + "source": "https://github.com/symfony/mime/tree/v7.4.0" }, "funding": [ { @@ -5082,16 +5478,20 @@ "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-04-27T13:34:41+00:00" + "time": "2025-11-16T10:14:42+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -5150,7 +5550,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -5161,6 +5561,10 @@ "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" @@ -5170,16 +5574,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -5228,7 +5632,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -5239,16 +5643,20 @@ "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": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -5311,7 +5719,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -5322,6 +5730,10 @@ "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" @@ -5331,7 +5743,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -5392,7 +5804,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -5403,6 +5815,10 @@ "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" @@ -5412,7 +5828,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -5473,7 +5889,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -5484,6 +5900,10 @@ "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" @@ -5493,7 +5913,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -5553,7 +5973,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -5564,6 +5984,10 @@ "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" @@ -5573,16 +5997,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", "shasum": "" }, "require": { @@ -5629,7 +6053,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -5640,25 +6064,109 @@ "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": "2024-09-09T11:45:10+00:00" + "time": "2025-07-08T02:45:35+00:00" + }, + { + "name": "symfony/polyfill-php85", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php85\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + }, + "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-06-23T16:12:55+00:00" }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f", + "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f", "shasum": "" }, "require": { @@ -5690,7 +6198,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.4.3" }, "funding": [ { @@ -5701,25 +6209,29 @@ "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-03-13T12:21:46+00:00" + "time": "2025-12-19T10:00:43+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -5737,7 +6249,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -5773,7 +6285,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -5784,31 +6296,36 @@ "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": "2024-09-25T14:20:29+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v7.2.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" + "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003", + "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-grapheme": "~1.33", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, @@ -5816,12 +6333,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5860,7 +6376,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.6" + "source": "https://github.com/symfony/string/tree/v7.4.0" }, "funding": [ { @@ -5871,34 +6387,39 @@ "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-04-20T20:18:16+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { "name": "symfony/translation", - "version": "v7.2.6", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6" + "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", - "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", + "url": "https://api.github.com/repos/symfony/translation/zipball/7ef27c65d78886f7599fdd5c93d12c9243ecf44d", + "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d", "shasum": "" }, "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "symfony/translation-contracts": "^2.5.3|^3.3" }, "conflict": { + "nikic/php-parser": "<5.0", "symfony/config": "<6.4", "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", @@ -5912,19 +6433,19 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5955,7 +6476,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.6" + "source": "https://github.com/symfony/translation/tree/v7.4.3" }, "funding": [ { @@ -5966,25 +6487,29 @@ "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-04-07T19:09:28+00:00" + "time": "2025-12-29T09:31:36+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.1", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "reference": "65a8bc82080447fae78373aa10f8d13b38338977" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", + "reference": "65a8bc82080447fae78373aa10f8d13b38338977", "shasum": "" }, "require": { @@ -5997,7 +6522,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -6033,7 +6558,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" }, "funding": [ { @@ -6044,40 +6569,44 @@ "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": "2024-09-25T14:20:29+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.2.6", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb" + "reference": "7e99bebcb3f90d8721890f2963463280848cba92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb", - "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92", + "reference": "7e99bebcb3f90d8721890f2963463280848cba92", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "symfony/console": "<6.4" }, "require-dev": { - "ext-iconv": "*", - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -6116,7 +6645,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.3" }, "funding": [ { @@ -6127,35 +6656,39 @@ "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-04-09T08:14:01+00:00" + "time": "2025-12-18T07:04:31+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.2", + "version": "v5.6.3", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + "reference": "955e7815d677a3eaa7075231212f2110983adecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.3", + "graham-campbell/result-type": "^1.1.4", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3", - "symfony/polyfill-ctype": "^1.24", - "symfony/polyfill-mbstring": "^1.24", - "symfony/polyfill-php80": "^1.24" + "phpoption/phpoption": "^1.9.5", + "symfony/polyfill-ctype": "^1.26", + "symfony/polyfill-mbstring": "^1.26", + "symfony/polyfill-php80": "^1.26" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -6204,7 +6737,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" }, "funding": [ { @@ -6216,7 +6749,7 @@ "type": "tidelift" } ], - "time": "2025-04-30T23:37:27+00:00" + "time": "2025-12-27T19:49:13+00:00" }, { "name": "voku/portable-ascii", @@ -6292,64 +6825,6 @@ ], "time": "2024-11-21T01:49:47+00:00" }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - }, { "name": "widmogrod/php-functional", "version": "6.0.2", @@ -6424,29 +6899,29 @@ "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", + "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", + "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -6465,9 +6940,9 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", @@ -6475,7 +6950,6 @@ } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -6496,9 +6970,28 @@ ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2023-01-05T11:28:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-11T04:32:07+00:00" }, { "name": "doctrine/instantiator", @@ -6706,16 +7199,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -6754,7 +7247,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -6762,20 +7255,20 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -6794,7 +7287,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -6818,9 +7311,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -6942,16 +7435,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.1.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", "shasum": "" }, "require": { @@ -6983,9 +7476,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" }, - "time": "2025-02-19T13:28:12+00:00" + "time": "2026-01-12T11:33:04+00:00" }, { "name": "phpunit/php-code-coverage", @@ -7624,16 +8117,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", "shasum": "" }, "require": { @@ -7686,15 +8179,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" }, "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": "2022-09-14T12:41:17+00:00" + "time": "2025-08-10T06:51:50+00:00" }, { "name": "sebastian/complexity", @@ -7884,16 +8389,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -7949,28 +8454,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "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": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", "shasum": "" }, "require": { @@ -8013,15 +8530,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" }, "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/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-08-10T07:10:35+00:00" }, { "name": "sebastian/lines-of-code", @@ -8194,16 +8723,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", "shasum": "" }, "require": { @@ -8245,15 +8774,27 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" }, "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": "2023-02-03T06:07:39+00:00" + "time": "2025-08-10T06:57:39+00:00" }, { "name": "sebastian/resource-operations", @@ -8420,32 +8961,32 @@ }, { "name": "slevomat/coding-standard", - "version": "8.18.0", + "version": "8.26.0", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593" + "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/f3b23cb9b26301b8c3c7bb03035a1bee23974593", - "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/d247cdc04b91956bdcfaa0b1313c01960b189d3c", + "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.0", "php": "^7.4 || ^8.0", - "phpstan/phpdoc-parser": "^2.1.0", - "squizlabs/php_codesniffer": "^3.12.2" + "phpstan/phpdoc-parser": "^2.3.0", + "squizlabs/php_codesniffer": "^4.0.1" }, "require-dev": { - "phing/phing": "3.0.1", + "phing/phing": "3.0.1|3.1.0", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.13", - "phpstan/phpstan-deprecation-rules": "2.0.2", - "phpstan/phpstan-phpunit": "2.0.6", - "phpstan/phpstan-strict-rules": "2.0.4", - "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.17|12.1.3" + "phpstan/phpstan": "2.1.33", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpstan/phpstan-phpunit": "2.0.11", + "phpstan/phpstan-strict-rules": "2.0.7", + "phpunit/phpunit": "9.6.31|10.5.60|11.4.4|11.5.46|12.5.4" }, "type": "phpcodesniffer-standard", "extra": { @@ -8469,7 +9010,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.18.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.26.0" }, "funding": [ { @@ -8481,41 +9022,36 @@ "type": "tidelift" } ], - "time": "2025-05-01T09:40:50+00:00" + "time": "2025-12-21T18:01:15+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.12.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa" + "reference": "0525c73950de35ded110cffafb9892946d7771b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", - "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5", + "reference": "0525c73950de35ded110cffafb9892946d7771b5", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.4.0" + "php": ">=7.2.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" }, "bin": [ "bin/phpcbf", "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -8534,7 +9070,7 @@ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", @@ -8565,20 +9101,20 @@ "type": "thanks_dev" } ], - "time": "2025-04-13T04:10:18+00:00" + "time": "2025-11-10T16:43:36+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -8607,7 +9143,7 @@ "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.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -8615,7 +9151,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php new file mode 100644 index 0000000..9f3c47a --- /dev/null +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -0,0 +1,101 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.7.0 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace Spotlibs\PhpLib\Libraries\StorageDrivers; + +use Aws\S3\S3Client; +use Illuminate\Filesystem\FilesystemAdapter; +use League\Flysystem\FilesystemAdapter as LeagueFsAdapter; +use League\Flysystem\FilesystemOperator; + +/** + * Storage + * + * @category Library + * @package Libraries + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class MinioAdapter extends FilesystemAdapter +{ + protected S3Client $publicClient; + protected string $bucket; + protected array $config; + + /** + * Create a new Minio Filesystem Adapter instance. + * + * @param FilesystemOperator $driver filesystem operator + * @param \League\Flysystem\FilesystemAdapter $adapter filesystem adapter + * @param array $config driver config + * @param S3Client $publicClient client for generating presigned URL + * + * @return void + */ + public function __construct(FilesystemOperator $driver, LeagueFsAdapter $adapter, array $config, S3Client $publicClient = null) + { + parent::__construct($driver, $adapter, $config); + + $this->bucket = $config['bucket']; + $this->config = $config; + + // Create public client for pre-signed URLs + $this->publicClient = $publicClient ?: new S3Client( + [ + 'credentials' => [ + 'key' => $config['key'], + 'secret' => $config['secret'] + ], + 'region' => $config['region'], + 'version' => 'latest', + 'use_path_style_endpoint' => true, + 'endpoint' => $config['url'] ?? $config['endpoint'], + ] + ); + } + + /** + * Temporary URL facade + * + * @param string $path file path + * @param string $expiration time limit of url + * @param array $options optional + * + * @return bool + */ + // phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + // phpcs:disable PEAR.Commenting.FunctionComment.Missing + public function temporaryUrl($path, $expiration, $options = []): string + { + $command = $this->publicClient->getCommand( + 'GetObject', + array_merge( + [ + 'Bucket' => $this->bucket, + 'Key' => $path, + ], + $options + ) + ); + + $request = $this->publicClient->createPresignedRequest( + $command, + $expiration + ); + + return (string) $request->getUri(); + } +} From 73ab4dcbcef3536416bfd31fbb308fb2ce5e31de Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 22 Jan 2026 15:42:56 +0700 Subject: [PATCH 23/42] switch back to coraxster --- composer.json | 2 +- composer.lock | 247 ++++++++---------- src/Libraries/StorageDrivers/MinioAdapter.php | 18 +- 3 files changed, 111 insertions(+), 156 deletions(-) diff --git a/composer.json b/composer.json index 8040873..31f02ea 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "laravel/lumen-framework": "^11.2.0", "jobcloud/php-kafka-lib": "~2.0.0", "flix-tech/avro-serde-php": "~2.1.0", - "league/flysystem-aws-s3-v3": "^3.30" + "coraxster/flysystem-aws-s3-v3-minio": "^1.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index b7a323a..b453c0b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "af43f19ec25ba2e225249956d25ef57f", + "content-hash": "96ce3e90e6b42d6ca0c98ac6576da716", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.16", + "version": "3.369.17", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "f7ae10a0b691d40075c801e3ae8735a722debfac" + "reference": "8bdccd2f8e54c5cd170b22f52414171e19226fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f7ae10a0b691d40075c801e3ae8735a722debfac", - "reference": "f7ae10a0b691d40075c801e3ae8735a722debfac", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8bdccd2f8e54c5cd170b22f52414171e19226fd1", + "reference": "8bdccd2f8e54c5cd170b22f52414171e19226fd1", "shasum": "" }, "require": { @@ -153,9 +153,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.16" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.17" }, - "time": "2026-01-20T19:44:30+00:00" + "time": "2026-01-21T19:09:32+00:00" }, { "name": "beberlei/assert", @@ -353,6 +353,56 @@ ], "time": "2024-02-09T16:56:22+00:00" }, + { + "name": "coraxster/flysystem-aws-s3-v3-minio", + "version": "1.0.16", + "source": { + "type": "git", + "url": "https://github.com/coraxster/flysystem-aws-s3-v3-minio.git", + "reference": "963b771021be0eda570064a2a5051e1192c3afbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/coraxster/flysystem-aws-s3-v3-minio/zipball/963b771021be0eda570064a2a5051e1192c3afbd", + "reference": "963b771021be0eda570064a2a5051e1192c3afbd", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.0.0", + "league/flysystem": "^1.0.40", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x, forked for minio support", + "support": { + "source": "https://github.com/coraxster/flysystem-aws-s3-v3-minio/tree/1.0.15-m" + }, + "time": "2017-09-26T08:08:44+00:00" + }, { "name": "doctrine/inflector", "version": "2.1.0", @@ -3238,55 +3288,54 @@ }, { "name": "league/flysystem", - "version": "3.30.2", + "version": "1.1.10", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277" + "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", - "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3239285c825c152bcc315fe0e87d6b55f5972ed1", + "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1", "shasum": "" }, "require": { - "league/flysystem-local": "^3.0.0", - "league/mime-type-detection": "^1.0.0", - "php": "^8.0.2" + "ext-fileinfo": "*", + "league/mime-type-detection": "^1.3", + "php": "^7.2.5 || ^8.0" }, "conflict": { - "async-aws/core": "<1.19.0", - "async-aws/s3": "<1.14.0", - "aws/aws-sdk-php": "3.209.31 || 3.210.0", - "guzzlehttp/guzzle": "<7.0", - "guzzlehttp/ringphp": "<1.1.1", - "phpseclib/phpseclib": "3.0.15", - "symfony/http-client": "<5.2" + "league/flysystem-sftp": "<1.0.6" }, "require-dev": { - "async-aws/s3": "^1.5 || ^2.0", - "async-aws/simple-s3": "^1.1 || ^2.0", - "aws/aws-sdk-php": "^3.295.10", - "composer/semver": "^3.0", - "ext-fileinfo": "*", - "ext-ftp": "*", - "ext-mongodb": "^1.3|^2", - "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.5", - "google/cloud-storage": "^1.23", - "guzzlehttp/psr7": "^2.6", - "microsoft/azure-storage-blob": "^1.1", - "mongodb/mongodb": "^1.2|^2", - "phpseclib/phpseclib": "^3.0.36", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.5.11|^10.0", - "sabre/dav": "^4.6.0" + "phpspec/prophecy": "^1.11.1", + "phpunit/phpunit": "^8.5.8" + }, + "suggest": { + "ext-ftp": "Allows you to use FTP server storage", + "ext-openssl": "Allows you to use FTPS server storage", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", + "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", + "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, "autoload": { "psr-4": { - "League\\Flysystem\\": "src" + "League\\Flysystem\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3296,132 +3345,40 @@ "authors": [ { "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" + "email": "info@frenky.net" } ], - "description": "File storage abstraction for PHP", + "description": "Filesystem abstraction: Many filesystems, one API.", "keywords": [ + "Cloud Files", "WebDAV", + "abstraction", "aws", "cloud", - "file", + "copy.com", + "dropbox", + "file systems", "files", "filesystem", "filesystems", "ftp", + "rackspace", + "remote", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.30.2" - }, - "time": "2025-11-10T17:13:11+00:00" - }, - { - "name": "league/flysystem-aws-s3-v3", - "version": "3.30.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "d286e896083bed3190574b8b088b557b59eb66f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/d286e896083bed3190574b8b088b557b59eb66f5", - "reference": "d286e896083bed3190574b8b088b557b59eb66f5", - "shasum": "" - }, - "require": { - "aws/aws-sdk-php": "^3.295.10", - "league/flysystem": "^3.10.0", - "league/mime-type-detection": "^1.0.0", - "php": "^8.0.2" + "source": "https://github.com/thephpleague/flysystem/tree/1.1.10" }, - "conflict": { - "guzzlehttp/guzzle": "<7.0", - "guzzlehttp/ringphp": "<1.1.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\Flysystem\\AwsS3V3\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" - } - ], - "description": "AWS S3 filesystem adapter for Flysystem.", - "keywords": [ - "Flysystem", - "aws", - "file", - "files", - "filesystem", - "s3", - "storage" - ], - "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.30.1" - }, - "time": "2025-10-20T15:27:33+00:00" - }, - { - "name": "league/flysystem-local", - "version": "3.30.2", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ab4f9d0d672f601b102936aa728801dd1a11968d", - "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d", - "shasum": "" - }, - "require": { - "ext-fileinfo": "*", - "league/flysystem": "^3.0.0", - "league/mime-type-detection": "^1.0.0", - "php": "^8.0.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\Flysystem\\Local\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" + "url": "https://offset.earth/frankdejonge", + "type": "other" } ], - "description": "Local filesystem adapter for Flysystem.", - "keywords": [ - "Flysystem", - "file", - "files", - "filesystem", - "local" - ], - "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.2" - }, - "time": "2025-11-10T11:23:37+00:00" + "time": "2022-10-04T09:16:37+00:00" }, { "name": "league/mime-type-detection", diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 9f3c47a..933c3f4 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -16,9 +16,8 @@ namespace Spotlibs\PhpLib\Libraries\StorageDrivers; use Aws\S3\S3Client; -use Illuminate\Filesystem\FilesystemAdapter; -use League\Flysystem\FilesystemAdapter as LeagueFsAdapter; -use League\Flysystem\FilesystemOperator; +use League\Flysystem\AwsS3v3\AwsS3Adapter; +use League\Flysystem\Filesystem; /** * Storage @@ -29,7 +28,7 @@ * @license https://mit-license.org/ MIT License * @link https://github.com/spotlibs */ -class MinioAdapter extends FilesystemAdapter +class MinioAdapter extends Filesystem { protected S3Client $publicClient; protected string $bucket; @@ -38,16 +37,15 @@ class MinioAdapter extends FilesystemAdapter /** * Create a new Minio Filesystem Adapter instance. * - * @param FilesystemOperator $driver filesystem operator - * @param \League\Flysystem\FilesystemAdapter $adapter filesystem adapter - * @param array $config driver config - * @param S3Client $publicClient client for generating presigned URL + * @param AwsS3Adapter $adapter filesystem adapter + * @param array $config driver config + * @param S3Client $publicClient client for generating presigned URL * * @return void */ - public function __construct(FilesystemOperator $driver, LeagueFsAdapter $adapter, array $config, S3Client $publicClient = null) + public function __construct(AwsS3Adapter $adapter, array $config, S3Client $publicClient) { - parent::__construct($driver, $adapter, $config); + parent::__construct($adapter, $config); $this->bucket = $config['bucket']; $this->config = $config; From 727723bee7111509bc2189744124f0b1496f8311 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 22 Jan 2026 15:50:02 +0700 Subject: [PATCH 24/42] fix bug $config must not be defined --- src/Libraries/StorageDrivers/MinioAdapter.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 933c3f4..41471cf 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -32,7 +32,6 @@ class MinioAdapter extends Filesystem { protected S3Client $publicClient; protected string $bucket; - protected array $config; /** * Create a new Minio Filesystem Adapter instance. @@ -48,7 +47,6 @@ public function __construct(AwsS3Adapter $adapter, array $config, S3Client $publ parent::__construct($adapter, $config); $this->bucket = $config['bucket']; - $this->config = $config; // Create public client for pre-signed URLs $this->publicClient = $publicClient ?: new S3Client( From f8d6ec3f8f19b2291ad77c85bf6a0f7e69953c8c Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 22 Jan 2026 16:10:21 +0700 Subject: [PATCH 25/42] add move and copy method to adapter --- src/Libraries/StorageDrivers/MinioAdapter.php | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 41471cf..965509b 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -94,4 +94,52 @@ public function temporaryUrl($path, $expiration, $options = []): string return (string) $request->getUri(); } + + /** + * Copy a file to a new location using S3 native copy. + * + * @param string $from source path + * @param string $to destination path + * + * @return bool + */ + public function copy(string $from, string $to): bool + { + try { + $this->client->copyObject( + [ + 'Bucket' => $this->bucket, + 'Key' => $to, + 'CopySource' => "{$this->bucket}/{$from}", + ] + ); + + return true; + } catch (\Exception $e) { + return false; + } + } + + /** + * Move a file to a new location using S3 native copy and delete. + * + * @param string $from source path + * @param string $to destination path + * + * @return bool + */ + public function move(string $from, string $to): bool + { + try { + // Copy the file + if ($this->copy($from, $to)) { + // Delete the original + return $this->delete($from); + } + + return false; + } catch (\Exception $e) { + return false; + } + } } From c47ee6278bb511eb0fc099a240d83474cdc88e39 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 22 Jan 2026 16:14:17 +0700 Subject: [PATCH 26/42] match lumen filesystem rule --- src/Libraries/StorageDrivers/MinioAdapter.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 965509b..cd487f8 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -123,18 +123,18 @@ public function copy(string $from, string $to): bool /** * Move a file to a new location using S3 native copy and delete. * - * @param string $from source path - * @param string $to destination path + * @param string $path source path + * @param string $newpath destination path * * @return bool */ - public function move(string $from, string $to): bool + public function move(string $path, string $newpath): bool { try { // Copy the file - if ($this->copy($from, $to)) { + if ($this->copy($path, $path)) { // Delete the original - return $this->delete($from); + return $this->delete($path); } return false; From 8e6e59f10bc555552bb4ea44d118570a2f276b2a Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Fri, 23 Jan 2026 08:26:25 +0700 Subject: [PATCH 27/42] change param to follow filesystem parent --- src/Libraries/StorageDrivers/MinioAdapter.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index cd487f8..0417af0 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -70,11 +70,11 @@ public function __construct(AwsS3Adapter $adapter, array $config, S3Client $publ * @param string $expiration time limit of url * @param array $options optional * - * @return bool + * @return string */ // phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint // phpcs:disable PEAR.Commenting.FunctionComment.Missing - public function temporaryUrl($path, $expiration, $options = []): string + public function temporaryUrl(string $path, string $expiration, array $options = []): string { $command = $this->publicClient->getCommand( 'GetObject', @@ -98,12 +98,12 @@ public function temporaryUrl($path, $expiration, $options = []): string /** * Copy a file to a new location using S3 native copy. * - * @param string $from source path - * @param string $to destination path + * @param string $path source path + * @param string $newpath destination path * * @return bool */ - public function copy(string $from, string $to): bool + public function copy($path, $newpath): bool { try { $this->client->copyObject( From e42f0aa89487b1f0a28cfc62ad97d8a9337d2522 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Fri, 23 Jan 2026 08:28:55 +0700 Subject: [PATCH 28/42] fix bug variable --- src/Libraries/StorageDrivers/MinioAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 0417af0..5f35927 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -132,7 +132,7 @@ public function move(string $path, string $newpath): bool { try { // Copy the file - if ($this->copy($path, $path)) { + if ($this->copy($path, $newpath)) { // Delete the original return $this->delete($path); } From 52f54f2a6755c4e982e4cafc9dc89e50792c8cd9 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Fri, 30 Jan 2026 09:46:40 +0700 Subject: [PATCH 29/42] filename --- src/Libraries/StorageDrivers/Minio.php | 22 ++++++++++--------- src/Libraries/StorageDrivers/NFS.php | 9 ++++---- .../StorageDrivers/StorageInterface.php | 7 +++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 0715274..f44001a 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -47,16 +47,18 @@ public function __construct(string $driver) /** * Upload file to disk * - * @param UploadedFile $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file + * @param string $filename optionally overide file name * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(UploadedFile $file, string $dirpath): bool + public function upload(UploadedFile $file, string $dirpath, string $filename = ""): bool { - FacadeStorage::disk('minio')->put($dirpath . "/" . $file->getClientOriginalName(), $file->getContent()); + $uploadPath = $dirpath . "/" . $filename == "" ? $file->getClientOriginalName() : $filename; + FacadeStorage::disk($this->driver)->put($uploadPath, $file->getContent()); return true; } /** @@ -71,7 +73,7 @@ public function upload(UploadedFile $file, string $dirpath): bool */ public function copy(string $srcPath, string $destPath): bool { - FacadeStorage::disk('minio')->copy($srcPath, $destPath); + FacadeStorage::disk($this->driver)->copy($srcPath, $destPath); return true; } /** @@ -85,7 +87,7 @@ public function copy(string $srcPath, string $destPath): bool */ public function delete(string $filepath): bool { - FacadeStorage::disk('minio')->delete($filepath); + FacadeStorage::disk($this->driver)->delete($filepath); return true; } /** @@ -100,7 +102,7 @@ public function delete(string $filepath): bool */ public function move(string $srcPath, string $destPath): bool { - FacadeStorage::disk('minio')->move($srcPath, $destPath); + FacadeStorage::disk($this->driver)->move($srcPath, $destPath); return true; } /** @@ -117,7 +119,7 @@ public function securelink(string $filepath): string * * @var \Illuminate\Filesystem\FilesystemAdapter $disk file storage disk */ - $disk = FacadeStorage::disk('minio'); + $disk = FacadeStorage::disk($this->driver); $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds((int) env('MINIO_EXPIRED_URL', 60))); return $urlpath; } @@ -135,11 +137,11 @@ public function securelinkFolder(string $dirpath): array if (!exec("mkdir $linkFolder")) { throw new RuntimeException("Failed to create securelink directory: $linkFolder"); } - $allFiles = FacadeStorage::disk(parent::$driver)->allFiles($dirpath); + $allFiles = FacadeStorage::disk($this->driver)->allFiles($dirpath); $result = []; foreach ($allFiles as $file) { $filename = parent::getFileName($file); - $fileStream = FacadeStorage::disk(parent::$driver)->readStream($file); + $fileStream = FacadeStorage::disk($this->driver)->readStream($file); $writeStream = fopen($linkFolder . "/" . $filename, 'w'); stream_copy_to_stream($fileStream, $writeStream); fclose($fileStream); diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index 4a175b2..a45fa12 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -45,21 +45,22 @@ public function __construct(string $driver) /** * Upload file to disk * - * @param UploadedFile $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file + * @param string $filename optionally overide file name * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(UploadedFile $file, string $dirpath): bool + public function upload(UploadedFile $file, string $dirpath, string $filename = ''): bool { if (!is_dir($dirpath)) { if (!mkdir($dirpath, 0664, true)) { throw new RuntimeException("Failed to create destination directory: $dirpath"); } } - $file->move($dirpath, $file->getClientOriginalName()); + $file->move($dirpath, $filename == '' ? $file->getClientOriginalName() : $filename); return true; } /** diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php index 6dcff3d..a33a390 100644 --- a/src/Libraries/StorageDrivers/StorageInterface.php +++ b/src/Libraries/StorageDrivers/StorageInterface.php @@ -31,14 +31,15 @@ interface StorageInterface /** * Upload file to disk * - * @param UploadedFile $file file from http request - * @param string $dirpath where to put the file + * @param UploadedFile $file file from http request + * @param string $dirpath where to put the file + * @param string $filename optionally overide file name * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * * @return bool */ - public function upload(UploadedFile $file, string $dirpath): bool; + public function upload(UploadedFile $file, string $dirpath, string $filename = ''): bool; /** * Copy file in disk * From 44508efb4cb1ea3d9a6f291a234db9573c96c73b Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Fri, 30 Jan 2026 10:28:18 +0700 Subject: [PATCH 30/42] fix bug filename path minio --- src/Libraries/StorageDrivers/Minio.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index f44001a..8ff4bcb 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -57,8 +57,8 @@ public function __construct(string $driver) */ public function upload(UploadedFile $file, string $dirpath, string $filename = ""): bool { - $uploadPath = $dirpath . "/" . $filename == "" ? $file->getClientOriginalName() : $filename; - FacadeStorage::disk($this->driver)->put($uploadPath, $file->getContent()); + $fileName = $filename == "" ? $file->getClientOriginalName() : $filename; + FacadeStorage::disk($this->driver)->put($dirpath . "/" . $fileName, $file->getContent()); return true; } /** From b1c02b6ebe4f2d0fa2f762f9a8218aa2dcddbb6c Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 5 Feb 2026 12:16:25 +0700 Subject: [PATCH 31/42] setting type for minio expiration --- src/Libraries/StorageDrivers/MinioAdapter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 5f35927..54c0da0 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -16,6 +16,7 @@ namespace Spotlibs\PhpLib\Libraries\StorageDrivers; use Aws\S3\S3Client; +use Carbon\Carbon; use League\Flysystem\AwsS3v3\AwsS3Adapter; use League\Flysystem\Filesystem; @@ -67,14 +68,14 @@ public function __construct(AwsS3Adapter $adapter, array $config, S3Client $publ * Temporary URL facade * * @param string $path file path - * @param string $expiration time limit of url + * @param int|string|Carbon $expiration time limit of url * @param array $options optional * * @return string */ // phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint // phpcs:disable PEAR.Commenting.FunctionComment.Missing - public function temporaryUrl(string $path, string $expiration, array $options = []): string + public function temporaryUrl(string $path, int|string|Carbon $expiration, array $options = []): string { $command = $this->publicClient->getCommand( 'GetObject', From b4dce5fb18c7e6d794298b102cc8dc1bdde67f5e Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 5 Feb 2026 14:14:25 +0700 Subject: [PATCH 32/42] fix permission issue on upload dir --- src/Libraries/StorageDrivers/NFS.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index a45fa12..15ffb22 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -56,7 +56,7 @@ public function __construct(string $driver) public function upload(UploadedFile $file, string $dirpath, string $filename = ''): bool { if (!is_dir($dirpath)) { - if (!mkdir($dirpath, 0664, true)) { + if (!mkdir($dirpath, 0755, true)) { throw new RuntimeException("Failed to create destination directory: $dirpath"); } } @@ -81,7 +81,7 @@ public function copy(string $srcPath, string $destPath): bool $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); if (!is_dir($destDir)) { - if (!mkdir($destDir, 0664, true)) { + if (!mkdir($destDir, 0755, true)) { throw new RuntimeException("Failed to create destination directory: $destDir"); } } @@ -125,7 +125,7 @@ public function move(string $srcPath, string $destPath): bool $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); if (!is_dir($destDir)) { - if (!mkdir($destDir, 0664, true)) { + if (!mkdir($destDir, 0755, true)) { throw new RuntimeException("Failed to create destination directory: $destDir"); } } From 2c68568df0915df198bb1b26a3708a5edb002f90 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 5 Feb 2026 16:58:38 +0700 Subject: [PATCH 33/42] fix wrong command --- src/Libraries/StorageDrivers/NFS.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index 15ffb22..2f210a4 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -85,8 +85,8 @@ public function copy(string $srcPath, string $destPath): bool throw new RuntimeException("Failed to create destination directory: $destDir"); } } - if (!exec("mv $srcPath $destPath")) { - throw new RuntimeException("Failed to move from $srcPath to $destPath"); + if (!exec("cp $srcPath $destPath")) { + throw new RuntimeException("Failed to copy from $srcPath to $destPath"); } return (bool) exec("chown -R 33:33 $destDir"); From 326cc949d5d5102c4ccc5e1eebef99a7fc8381c4 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 5 Feb 2026 18:12:37 +0700 Subject: [PATCH 34/42] non-aggresive error validation --- src/Libraries/StorageDrivers/NFS.php | 36 +++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index 2f210a4..e0de894 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -80,16 +80,18 @@ public function copy(string $srcPath, string $destPath): bool } $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); - if (!is_dir($destDir)) { - if (!mkdir($destDir, 0755, true)) { - throw new RuntimeException("Failed to create destination directory: $destDir"); + try { + if (!is_dir($destDir)) { + if (!mkdir($destDir, 0755, true)) { + throw new RuntimeException("Failed to create destination directory: $destDir"); + } } + exec("cp $srcPath $destPath"); + exec("chown -R 33:33 $destDir"); + } catch (\Throwable $th) { + throw new RuntimeException("Failed to copy from $srcPath to $destPath. " . $th->getMessage()); } - if (!exec("cp $srcPath $destPath")) { - throw new RuntimeException("Failed to copy from $srcPath to $destPath"); - } - - return (bool) exec("chown -R 33:33 $destDir"); + return true; } /** * Delete file in disk @@ -124,16 +126,18 @@ public function move(string $srcPath, string $destPath): bool { $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); - if (!is_dir($destDir)) { - if (!mkdir($destDir, 0755, true)) { - throw new RuntimeException("Failed to create destination directory: $destDir"); + try { + if (!is_dir($destDir)) { + if (!mkdir($destDir, 0755, true)) { + throw new RuntimeException("Failed to create destination directory: $destDir"); + } } + exec("mv $srcPath $destPath"); + exec("chown -R 33:33 $destDir"); + } catch (\Throwable $th) { + throw new RuntimeException("Failed to move from $srcPath to $destPath. " . $th->getMessage()); } - if (!exec("mv $srcPath $destPath")) { - throw new RuntimeException("Failed to move from $srcPath to $destPath"); - } - - return (bool) exec("chown -R 33:33 $destDir"); + return true; } /** * Create temporary URL for file in disk From 239eb379c154947c4f068a86d5287a0282032797 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Sun, 8 Feb 2026 01:58:28 +0700 Subject: [PATCH 35/42] update storage driver. disable static call for testable code --- phpunit.xml | 2 ++ src/Libraries/Storage.php | 28 --------------- src/Libraries/StorageDrivers/Minio.php | 19 +++++++--- src/Libraries/StorageDrivers/NFS.php | 49 +++++++++++++------------- 4 files changed, 42 insertions(+), 56 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 57ededb..3c5e38b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -32,11 +32,13 @@ src/Exceptions/Handler.php src/Libraries/Kafka.php src/Libraries/KafkaCallable.php + src/Libraries/Storage.php src/Commands src/Facades src/Middlewares src/Providers src/Validations + src/Libraries/StorageDrivers diff --git a/src/Libraries/Storage.php b/src/Libraries/Storage.php index 7f98128..69b3cb6 100644 --- a/src/Libraries/Storage.php +++ b/src/Libraries/Storage.php @@ -16,9 +16,6 @@ namespace Spotlibs\PhpLib\Libraries; use Spotlibs\PhpLib\Exceptions\RuntimeException; -use Spotlibs\PhpLib\Libraries\StorageDrivers\Minio; -use Spotlibs\PhpLib\Libraries\StorageDrivers\NFS; -use Spotlibs\PhpLib\Libraries\StorageDrivers\StorageInterface; /** * Storage @@ -32,32 +29,7 @@ class Storage { protected string $driver; - /** - * Create a new Storage instance for the specified driver. - * - * @param string $driver The storage driver to use. - * - * @return \Spotlibs\PhpLib\Libraries\StorageDrivers\StorageInterface - */ - public static function disk(string $driver): StorageInterface - { - if (str_contains(strtolower($driver), "minio")) { - return new Minio($driver); - } - return new NFS($driver); - } - /** - * Create a new Storage instance. - * - * @param string $driver driver name. example: nfs_xxx - * - * @return void - */ - public function __construct(string $driver) - { - $this->driver = $driver; - } /** * Parse file name from filepath * diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 8ff4bcb..71a2dcc 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -36,13 +36,24 @@ class Minio extends Storage implements StorageInterface /** * Create a new NFS instance. * - * @param string $driver driver name. example: minio_xxx - * * @return void */ - public function __construct(string $driver) + public function __construct() + { + $this->driver = "minio"; + } + + /** + * Set disk driver for different minio config setup in config/filesystem.php + * + * @param string $driver driver name according to config setup in config/filesystem.php + * + * @return Minio + */ + public function disk(string $driver): self { - parent::__construct($driver); + $this->driver = $driver; + return $this; } /** * Upload file to disk diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index e0de894..f6e94d2 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -31,17 +31,6 @@ */ class NFS extends Storage implements StorageInterface { - /** - * Create a new NFS instance. - * - * @param string $driver driver name. example: nfs_xxx - * - * @return void - */ - public function __construct(string $driver) - { - parent::__construct($driver); - } /** * Upload file to disk * @@ -81,13 +70,8 @@ public function copy(string $srcPath, string $destPath): bool $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); try { - if (!is_dir($destDir)) { - if (!mkdir($destDir, 0755, true)) { - throw new RuntimeException("Failed to create destination directory: $destDir"); - } - } + $this->createDirectory($destDir); exec("cp $srcPath $destPath"); - exec("chown -R 33:33 $destDir"); } catch (\Throwable $th) { throw new RuntimeException("Failed to copy from $srcPath to $destPath. " . $th->getMessage()); } @@ -116,7 +100,7 @@ public function delete(string $filepath): bool * Move file in disk * * @param string $srcPath source file path - * @param string $destPath destination file path + * @param string $destPath destination file path, include filename if you want to change its name * * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException * @@ -127,13 +111,8 @@ public function move(string $srcPath, string $destPath): bool $tmp = explode("/", $destPath); $destDir = implode("/", array_slice($tmp, 0, -1)); try { - if (!is_dir($destDir)) { - if (!mkdir($destDir, 0755, true)) { - throw new RuntimeException("Failed to create destination directory: $destDir"); - } - } + $this->createDirectory($destDir); exec("mv $srcPath $destPath"); - exec("chown -R 33:33 $destDir"); } catch (\Throwable $th) { throw new RuntimeException("Failed to move from $srcPath to $destPath. " . $th->getMessage()); } @@ -183,4 +162,26 @@ public function securelinkFolder(string $dirpath): array } return $result; } + /** + * Create new directory in NFS + * + * @param string $dirpath path of new directory + * + * @throws RuntimeException + * + * @return void + */ + private function createDirectory(string $dirpath): void + { + try { + if (!is_dir($dirpath)) { + if (!mkdir($dirpath, 0755, true)) { + throw new RuntimeException("Failed to create destination directory: $dirpath"); + } + } + exec("chown -R 33:33 $dirpath"); + } catch (\Throwable $th) { + throw new RuntimeException("Failed to create new directory" . $th->getMessage()); + } + } } From 20318d6c78d287fcd4bda868f3e50e39bfbfb163 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 18 Feb 2026 10:06:06 +0700 Subject: [PATCH 36/42] fix nfs securelink bug --- src/Libraries/StorageDrivers/NFS.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index f6e94d2..ab6ffe7 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -132,8 +132,10 @@ public function securelink(string $filepath): string if (!is_file($filepath)) { throw new RuntimeException("File not found within filepath: $filepath"); } + $extension = $this->getExtension($filepath); $random = Str::random(40); - if (!exec("ln -s $filepath /var/www/html/public/securelink/$random")) { + $random = $extension !== "" ? "$random.$extension" : $random; + if (!exec("ln -s \"$filepath\" /var/www/html/public/securelink/$random")) { throw new RuntimeException("Failed to create secure link for file: $filepath"); } return env('APP_URL') . "/securelink/$random"; @@ -184,4 +186,21 @@ private function createDirectory(string $dirpath): void throw new RuntimeException("Failed to create new directory" . $th->getMessage()); } } + + /** + * Extract file's extension + * + * @param string $filepath path of the file + * + * @return string + */ + private function getExtension(string $filepath): string + { + $temp = explode("/", $filepath); + $temp = explode(".", $temp[\count($temp) - 1]); + if (\count($temp) > 0) { + return $temp[1]; + } + return ""; + } } From dc81283de0fbe1ed372d9e453d0ccda815b9b6a0 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 18 Feb 2026 10:25:31 +0700 Subject: [PATCH 37/42] fix nfs securelink bug --- src/Libraries/StorageDrivers/NFS.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index ab6ffe7..a24185b 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -135,7 +135,8 @@ public function securelink(string $filepath): string $extension = $this->getExtension($filepath); $random = Str::random(40); $random = $extension !== "" ? "$random.$extension" : $random; - if (!exec("ln -s \"$filepath\" /var/www/html/public/securelink/$random")) { + exec("ln -s \"$filepath\" /var/www/html/public/securelink/$random", $output, $exit_code); + if ($exit_code !== 0) { throw new RuntimeException("Failed to create secure link for file: $filepath"); } return env('APP_URL') . "/securelink/$random"; From fd6b64b0a7f235338d8218900dbd8be24fd2ce25 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Wed, 18 Feb 2026 16:35:38 +0700 Subject: [PATCH 38/42] update minio facade --- src/Libraries/Storage.php | 9 +---- src/Libraries/StorageDrivers/Minio.php | 9 +++-- src/Libraries/StorageDrivers/MinioAdapter.php | 38 ++++++++----------- src/Libraries/StorageDrivers/NFS.php | 8 ++-- 4 files changed, 25 insertions(+), 39 deletions(-) diff --git a/src/Libraries/Storage.php b/src/Libraries/Storage.php index 69b3cb6..58badad 100644 --- a/src/Libraries/Storage.php +++ b/src/Libraries/Storage.php @@ -15,8 +15,6 @@ namespace Spotlibs\PhpLib\Libraries; -use Spotlibs\PhpLib\Exceptions\RuntimeException; - /** * Storage * @@ -35,15 +33,10 @@ class Storage * * @param string $filepath path of the file * - * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException - * * @return string */ protected function getFileName(string $filepath): string { - if ($x = explode("/", $filepath)) { - return $x[-1]; - } - throw new RuntimeException("failed to get filename from $filepath"); + return basename($filepath); } } diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 71a2dcc..701515f 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -145,20 +145,21 @@ public function securelinkFolder(string $dirpath): array { $random = Str::random(40); $linkFolder = "/var/www/html/public/securelink/$random"; - if (!exec("mkdir $linkFolder")) { + if (!mkdir($linkFolder, 0755, true)) { throw new RuntimeException("Failed to create securelink directory: $linkFolder"); } $allFiles = FacadeStorage::disk($this->driver)->allFiles($dirpath); $result = []; foreach ($allFiles as $file) { - $filename = parent::getFileName($file); - $fileStream = FacadeStorage::disk($this->driver)->readStream($file); + $filename = parent::getFileName($file["path"]); + $fileStream = FacadeStorage::disk($this->driver)->readStream($file["path"]); $writeStream = fopen($linkFolder . "/" . $filename, 'w'); stream_copy_to_stream($fileStream, $writeStream); fclose($fileStream); fclose($writeStream); - $result[] = env('APP_URL') . "/securelink/" . $linkFolder . "/" . $filename; + $result[] = env('APP_URL') . "/securelink/" . $random . "/" . $filename; } + return $result; } } diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php index 54c0da0..9e81450 100644 --- a/src/Libraries/StorageDrivers/MinioAdapter.php +++ b/src/Libraries/StorageDrivers/MinioAdapter.php @@ -97,50 +97,42 @@ public function temporaryUrl(string $path, int|string|Carbon $expiration, array } /** - * Copy a file to a new location using S3 native copy. + * Move a file to a new location using S3 native copy and delete. * * @param string $path source path * @param string $newpath destination path * * @return bool */ - public function copy($path, $newpath): bool + public function move(string $path, string $newpath): bool { try { - $this->client->copyObject( - [ - 'Bucket' => $this->bucket, - 'Key' => $to, - 'CopySource' => "{$this->bucket}/{$from}", - ] - ); + // Copy the file + if ($this->copy($path, $newpath)) { + // Delete the original + return $this->delete($path); + } - return true; + return false; } catch (\Exception $e) { return false; } } /** - * Move a file to a new location using S3 native copy and delete. + * Get all files in a directory * - * @param string $path source path - * @param string $newpath destination path + * @param string $dirpath path of the directory * * @return bool */ - public function move(string $path, string $newpath): bool + public function allFiles(string $dirpath): array { try { - // Copy the file - if ($this->copy($path, $newpath)) { - // Delete the original - return $this->delete($path); - } - - return false; - } catch (\Exception $e) { - return false; + $paths = $this->listContents($dirpath); + return $paths; + } catch (\Throwable $th) { + throw $th; } } } diff --git a/src/Libraries/StorageDrivers/NFS.php b/src/Libraries/StorageDrivers/NFS.php index a24185b..b19110c 100644 --- a/src/Libraries/StorageDrivers/NFS.php +++ b/src/Libraries/StorageDrivers/NFS.php @@ -156,12 +156,13 @@ public function securelinkFolder(string $dirpath): array throw new RuntimeException("Directory not found within dirpath: $dirpath"); } $random = Str::random(40); - if (!exec("ln -sf $dirpath /var/www/html/public/securelink/$random")) { + exec("ln -sf $dirpath /var/www/html/public/securelink/$random", $output, $exit_code); + if ($exit_code !== 0) { throw new RuntimeException("Failed to create secure link for file: $dirpath"); } $result = glob("/var/www/html/public/securelink/$random/*"); foreach ($result as $key => $r) { - $result[$key] = str_replace("/var/www/html", env('APP_URL'), $r); + $result[$key] = str_replace("/var/www/html/public", env('APP_URL'), $r); } return $result; } @@ -197,8 +198,7 @@ private function createDirectory(string $dirpath): void */ private function getExtension(string $filepath): string { - $temp = explode("/", $filepath); - $temp = explode(".", $temp[\count($temp) - 1]); + $temp = explode(".", basename($filepath)); if (\count($temp) > 0) { return $temp[1]; } From d17bbe9f0422190f6f1ea53ab162c22914e1f3cb Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 19 Feb 2026 14:59:46 +0700 Subject: [PATCH 39/42] deps control --- composer.json | 13 +- composer.lock | 2639 ++++++++++++++++++++----------------------------- 2 files changed, 1059 insertions(+), 1593 deletions(-) diff --git a/composer.json b/composer.json index 31f02ea..0f25c9e 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,10 @@ "license": "MIT", "type": "library", "require": { - "php": "^8.3", - "laravel/lumen-framework": "^11.2.0", - "jobcloud/php-kafka-lib": "~2.0.0", - "flix-tech/avro-serde-php": "~2.1.0", + "php": "^7.3|^8.0", + "laravel/lumen-framework": "^8.0", + "jobcloud/php-kafka-lib": "^1.7", + "flix-tech/avro-serde-php": "^1.7", "coraxster/flysystem-aws-s3-v3-minio": "^1.0" }, "autoload": { @@ -33,10 +33,5 @@ "scripts": { "lint": "./vendor/bin/phpcs -p", "test": "./vendor/bin/phpunit --configuration phpunit.xml --coverage-clover report_coverage.xml && php prepare-coverage-report.php && ./vendor/bin/coverage-check report_coverage.xml 40" - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } } } diff --git a/composer.lock b/composer.lock index b453c0b..41c66b5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "96ce3e90e6b42d6ca0c98ac6576da716", + "content-hash": "82c5862031b247e0f468c8d6fca45b62", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.17", + "version": "3.337.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "8bdccd2f8e54c5cd170b22f52414171e19226fd1" + "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8bdccd2f8e54c5cd170b22f52414171e19226fd1", - "reference": "8bdccd2f8e54c5cd170b22f52414171e19226fd1", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/06dfc8f76423b49aaa181debd25bbdc724c346d6", + "reference": "06dfc8f76423b49aaa181debd25bbdc724c346d6", "shasum": "" }, "require": { @@ -79,36 +79,37 @@ "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/promises": "^2.0", - "guzzlehttp/psr7": "^2.4.5", - "mtdowling/jmespath.php": "^2.8.0", - "php": ">=8.1", - "psr/http-message": "^1.0 || ^2.0", - "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", - "composer/composer": "^2.7.8", + "composer/composer": "^1.10.22", "dms/phpunit-arraysubset-asserts": "^0.4.0", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", + "ext-pcntl": "*", "ext-sockets": "*", - "phpunit/phpunit": "^9.6", - "psr/cache": "^2.0 || ^3.0", - "psr/simple-cache": "^2.0 || ^3.0", - "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", - "yoast/phpunit-polyfills": "^2.0" + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" }, "suggest": { "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", "doctrine/cache": "To use the DoctrineCacheAdapter", "ext-curl": "To send requests using cURL", "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", - "ext-pcntl": "To use client-side monitoring", "ext-sockets": "To use client-side monitoring" }, "type": "library", @@ -151,11 +152,11 @@ "sdk" ], "support": { - "forum": "https://github.com/aws/aws-sdk-php/discussions", + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.17" + "source": "https://github.com/aws/aws-sdk-php/tree/3.337.3" }, - "time": "2026-01-21T19:09:32+00:00" + "time": "2025-01-21T19:10:05+00:00" }, { "name": "beberlei/assert", @@ -226,25 +227,25 @@ }, { "name": "brick/math", - "version": "0.14.1", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", + "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", "shasum": "" }, "require": { - "php": "^8.2" + "php": "^8.0" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "2.1.22", - "phpunit/phpunit": "^11.5" + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" }, "type": "library", "autoload": { @@ -264,17 +265,12 @@ "arithmetic", "bigdecimal", "bignum", - "bignumber", "brick", - "decimal", - "integer", - "math", - "mathematics", - "rational" + "math" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.1" + "source": "https://github.com/brick/math/tree/0.11.0" }, "funding": [ { @@ -282,30 +278,30 @@ "type": "github" } ], - "time": "2025-11-24T14:40:29+00:00" + "time": "2023-01-15T23:15:59+00:00" }, { "name": "carbonphp/carbon-doctrine-types", - "version": "3.2.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", - "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", - "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.4 || ^8.0" }, "conflict": { - "doctrine/dbal": "<4.0.0 || >=5.0.0" + "doctrine/dbal": "<3.7.0 || >=4.0.0" }, "require-dev": { - "doctrine/dbal": "^4.0.0", + "doctrine/dbal": "^3.7.0", "nesbot/carbon": "^2.71.0 || ^3.0.0", "phpunit/phpunit": "^10.3" }, @@ -335,7 +331,7 @@ ], "support": { "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", - "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" }, "funding": [ { @@ -351,7 +347,7 @@ "type": "tidelift" } ], - "time": "2024-02-09T16:56:22+00:00" + "time": "2023-12-11T17:09:12+00:00" }, { "name": "coraxster/flysystem-aws-s3-v3-minio", @@ -495,32 +491,31 @@ }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } }, "notification-url": "https://packagist.org/downloads/", @@ -552,7 +547,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/1.2.3" }, "funding": [ { @@ -568,24 +563,24 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2022-02-28T11:07:21+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.6.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" + "reference": "1b2de7f4a468165dca07b142240733a1973e766d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", - "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/1b2de7f4a468165dca07b142240733a1973e766d", + "reference": "1b2de7f4a468165dca07b142240733a1973e766d", "shasum": "" }, "require": { - "php": "^8.2|^8.3|^8.4|^8.5" + "php": "^7.2|^8.0" }, "replace": { "mtdowling/cron-expression": "^1.0" @@ -624,7 +619,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.5.0" }, "funding": [ { @@ -632,30 +627,31 @@ "type": "github" } ], - "time": "2025-10-31T18:51:33+00:00" + "time": "2025-10-31T18:36:32+00:00" }, { "name": "egulias/email-validator", - "version": "4.0.4", + "version": "2.1.25", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", - "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", "shasum": "" }, "require": { - "doctrine/lexer": "^2.0 || ^3.0", - "php": ">=8.1", - "symfony/polyfill-intl-idn": "^1.26" + "doctrine/lexer": "^1.0.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.10" }, "require-dev": { - "phpunit/phpunit": "^10.2", - "vimeo/psalm": "^5.12" + "dominicsayers/isemail": "^3.0.7", + "phpunit/phpunit": "^4.8.36|^7.5.15", + "satooshi/php-coveralls": "^1.0.1" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -663,7 +659,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -691,7 +687,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" }, "funding": [ { @@ -699,27 +695,27 @@ "type": "github" } ], - "time": "2025-03-06T22:45:56+00:00" + "time": "2020-12-29T14:50:06+00:00" }, { "name": "flix-tech/avro-php", - "version": "5.1.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/flix-tech/avro-php.git", - "reference": "1d537bfe4ecab405917d15eee8f2020743fc8596" + "reference": "5936698fab7d3593ef73b6632f2c0d07ba2267f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/avro-php/zipball/1d537bfe4ecab405917d15eee8f2020743fc8596", - "reference": "1d537bfe4ecab405917d15eee8f2020743fc8596", + "url": "https://api.github.com/repos/flix-tech/avro-php/zipball/5936698fab7d3593ef73b6632f2c0d07ba2267f6", + "reference": "5936698fab7d3593ef73b6632f2c0d07ba2267f6", "shasum": "" }, "require": { - "php": "^8.1" + "php": ">=7.4|>=8.0" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "~8.5" }, "suggest": { "ext-gmp": "Large integer support for 32-bit platforms.", @@ -738,37 +734,36 @@ ], "description": "Avro schema encoder/decoder. Fork of rg/avro-php", "support": { - "source": "https://github.com/flix-tech/avro-php/tree/5.1.1" + "source": "https://github.com/flix-tech/avro-php/tree/4.3.0" }, - "time": "2025-01-24T05:04:07+00:00" + "time": "2022-08-10T07:34:07+00:00" }, { "name": "flix-tech/avro-serde-php", - "version": "2.1.0", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/flix-tech/avro-serde-php.git", - "reference": "ffeab369fe3631d2a076ef9744f0ee2dcab2238c" + "reference": "b6b6baaf01a54d314ed957598c0740064b572aad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/avro-serde-php/zipball/ffeab369fe3631d2a076ef9744f0ee2dcab2238c", - "reference": "ffeab369fe3631d2a076ef9744f0ee2dcab2238c", + "url": "https://api.github.com/repos/flix-tech/avro-serde-php/zipball/b6b6baaf01a54d314ed957598c0740064b572aad", + "reference": "b6b6baaf01a54d314ed957598c0740064b572aad", "shasum": "" }, "require": { "beberlei/assert": "^2.9.9|~3.0", - "flix-tech/avro-php": "^5.0", - "flix-tech/confluent-schema-registry-api": "^8.0", - "guzzlehttp/promises": "^1.4.0|^2.0.0", + "flix-tech/avro-php": "^4.1.0", + "flix-tech/confluent-schema-registry-api": "^7.3.1", + "guzzlehttp/promises": "^1.4.0", "php": "^7.3|^8.0", "widmogrod/php-functional": "^6.0" }, "require-dev": { "doctrine/annotations": "^1.11", "phpbench/phpbench": "1.0.0-alpha2", - "phpunit/phpunit": "^9.4.2", - "roave/security-advisories": "dev-latest", + "phpunit/phpunit": "^8.2.3|^9.4.2", "symfony/serializer": "^3.4|^4.3", "vlucas/phpdotenv": "~2.4" }, @@ -820,33 +815,33 @@ ], "support": { "issues": "https://github.com/flix-tech/avro-serde-php/issues", - "source": "https://github.com/flix-tech/avro-serde-php/tree/2.1.0" + "source": "https://github.com/flix-tech/avro-serde-php/tree/1.7.2" }, - "time": "2024-01-26T13:39:27+00:00" + "time": "2022-06-30T14:21:32+00:00" }, { "name": "flix-tech/confluent-schema-registry-api", - "version": "8.1.0", + "version": "7.6.1", "source": { "type": "git", "url": "https://github.com/flix-tech/schema-registry-php-client.git", - "reference": "87023aebb0393da62d932b9be49d0d891a52ae37" + "reference": "89817110145f6bc4690bbeb190c3e5b4f733ba12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flix-tech/schema-registry-php-client/zipball/87023aebb0393da62d932b9be49d0d891a52ae37", - "reference": "87023aebb0393da62d932b9be49d0d891a52ae37", + "url": "https://api.github.com/repos/flix-tech/schema-registry-php-client/zipball/89817110145f6bc4690bbeb190c3e5b4f733ba12", + "reference": "89817110145f6bc4690bbeb190c3e5b4f733ba12", "shasum": "" }, "require": { "beberlei/assert": "~2.7|~3.0", "ext-curl": "*", "ext-json": "*", - "flix-tech/avro-php": "^5.0", + "flix-tech/avro-php": "^4.3", "guzzlehttp/guzzle": "^7.0", - "guzzlehttp/promises": "^1.4.0|^2.0.0", + "guzzlehttp/promises": "^1.4.0", "guzzlehttp/psr7": "^1.7|^2.1", - "php": "^7.4|^8.0" + "php": "^7.4|^8.0|^8.1" }, "require-dev": { "doctrine/cache": "~1.3", @@ -884,80 +879,9 @@ "description": "A PHP 7.4+ library to consume the Confluent Schema Registry REST API.", "support": { "issues": "https://github.com/flix-tech/schema-registry-php-client/issues", - "source": "https://github.com/flix-tech/schema-registry-php-client/tree/8.1.0" - }, - "time": "2024-01-26T13:22:35+00:00" - }, - { - "name": "fruitcake/php-cors", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/fruitcake/php-cors.git", - "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", - "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", - "shasum": "" - }, - "require": { - "php": "^8.1", - "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" - }, - "require-dev": { - "phpstan/phpstan": "^2", - "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Fruitcake\\Cors\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fruitcake", - "homepage": "https://fruitcake.nl" - }, - { - "name": "Barryvdh", - "email": "barryvdh@gmail.com" - } - ], - "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", - "homepage": "https://github.com/fruitcake/php-cors", - "keywords": [ - "cors", - "laravel", - "symfony" - ], - "support": { - "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" + "source": "https://github.com/flix-tech/schema-registry-php-client/tree/7.6.1" }, - "funding": [ - { - "url": "https://fruitcake.nl", - "type": "custom" - }, - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2025-12-03T09:33:47+00:00" + "time": "2022-08-24T08:12:15+00:00" }, { "name": "functional-php/fantasy-land", @@ -1071,22 +995,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.10.0", + "version": "7.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.3", - "guzzlehttp/psr7": "^2.8", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1177,7 +1101,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" }, "funding": [ { @@ -1193,37 +1117,33 @@ "type": "tidelift" } ], - "time": "2025-08-23T22:36:01+00:00" + "time": "2025-03-27T13:37:11+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.3.0", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": ">=5.5" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -1260,7 +1180,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.3.0" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -1276,7 +1196,7 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:34:08+00:00" + "time": "2023-05-21T12:31:43+00:00" }, { "name": "guzzlehttp/psr7", @@ -1394,125 +1314,38 @@ ], "time": "2025-08-23T21:21:41+00:00" }, - { - "name": "guzzlehttp/uri-template", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "https://github.com/guzzle/uri-template.git", - "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", - "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "symfony/polyfill-php80": "^1.24" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25", - "uri-template/tests": "1.0.0" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\UriTemplate\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - } - ], - "description": "A polyfill class for uri_template of PHP", - "keywords": [ - "guzzlehttp", - "uri-template" - ], - "support": { - "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", - "type": "tidelift" - } - ], - "time": "2025-08-22T14:27:06+00:00" - }, { "name": "illuminate/auth", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/auth.git", - "reference": "474944fb7cc40942db14cb70db88eab810c46426" + "reference": "28e3e57f777685018374bb59bbaa54598dbdf441" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/auth/zipball/474944fb7cc40942db14cb70db88eab810c46426", - "reference": "474944fb7cc40942db14cb70db88eab810c46426", + "url": "https://api.github.com/repos/illuminate/auth/zipball/28e3e57f777685018374bb59bbaa54598dbdf441", + "reference": "28e3e57f777685018374bb59bbaa54598dbdf441", "shasum": "" }, "require": { - "ext-hash": "*", - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/http": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/queue": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/http": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "suggest": { - "illuminate/console": "Required to use the auth:clear-resets command (^11.0).", - "illuminate/queue": "Required to fire login / logout events (^11.0).", - "illuminate/session": "Required to use the session based guard (^11.0)." + "illuminate/console": "Required to use the auth:clear-resets command (^8.0).", + "illuminate/queue": "Required to fire login / logout events (^8.0).", + "illuminate/session": "Required to use the session based guard (^8.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1536,41 +1369,40 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-05-11T20:46:35+00:00" + "time": "2022-09-21T21:30:03+00:00" }, { "name": "illuminate/broadcasting", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/broadcasting.git", - "reference": "2980909486df6a4d5a26d979edda20200982822f" + "reference": "d7c0c81bcc679c294746b161f4b834997e904cf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/broadcasting/zipball/2980909486df6a4d5a26d979edda20200982822f", - "reference": "2980909486df6a4d5a26d979edda20200982822f", + "url": "https://api.github.com/repos/illuminate/broadcasting/zipball/d7c0c81bcc679c294746b161f4b834997e904cf4", + "reference": "d7c0c81bcc679c294746b161f4b834997e904cf4", "shasum": "" }, "require": { - "illuminate/bus": "^11.0", - "illuminate/collections": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/queue": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2", - "psr/log": "^1.0|^2.0|^3.0" + "ext-json": "*", + "illuminate/bus": "^8.0", + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "psr/log": "^1.0|^2.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "ext-hash": "Required to use the Ably and Pusher broadcast drivers.", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0)." + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0|^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1594,28 +1426,28 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-01-06T14:28:26+00:00" }, { "name": "illuminate/bus", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/bus.git", - "reference": "2adf211bada7184410501b37882845230d6bf2f4" + "reference": "d2a8ae4bfd881086e55455e470776358eab27eae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/bus/zipball/2adf211bada7184410501b37882845230d6bf2f4", - "reference": "2adf211bada7184410501b37882845230d6bf2f4", + "url": "https://api.github.com/repos/illuminate/bus/zipball/d2a8ae4bfd881086e55455e470776358eab27eae", + "reference": "d2a8ae4bfd881086e55455e470776358eab27eae", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/pipeline": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "suggest": { "illuminate/queue": "Required to use closures when chaining jobs (^7.0)." @@ -1623,7 +1455,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1647,45 +1479,43 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-10-14T19:59:30+00:00" + "time": "2022-03-07T15:02:42+00:00" }, { "name": "illuminate/cache", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/cache.git", - "reference": "f9196623f6b75f7e69b9ac92f367491909753987" + "reference": "7ae5b3661413dad7264b5c69037190d766bae50f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/cache/zipball/f9196623f6b75f7e69b9ac92f367491909753987", - "reference": "f9196623f6b75f7e69b9ac92f367491909753987", + "url": "https://api.github.com/repos/illuminate/cache/zipball/7ae5b3661413dad7264b5c69037190d766bae50f", + "reference": "7ae5b3661413dad7264b5c69037190d766bae50f", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "provide": { - "psr/simple-cache-implementation": "1.0|2.0|3.0" + "psr/simple-cache-implementation": "1.0" }, "suggest": { - "ext-apcu": "Required to use the APC cache driver.", - "ext-filter": "Required to use the DynamoDb cache driver.", "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^11.0).", - "illuminate/filesystem": "Required to use the file cache driver (^11.0).", - "illuminate/redis": "Required to use the redis cache driver (^11.0).", - "symfony/cache": "Required to use PSR-6 cache bridge (^7.0)." + "illuminate/database": "Required to use the database cache driver (^8.0).", + "illuminate/filesystem": "Required to use the file cache driver (^8.0).", + "illuminate/redis": "Required to use the redis cache driver (^8.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.4)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1709,40 +1539,38 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-01-27T22:47:27+00:00" + "time": "2022-07-22T14:58:32+00:00" }, { "name": "illuminate/collections", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "856b1da953e46281ba61d7c82d337072d3ee1825" + "reference": "705a4e1ef93cd492c45b9b3e7911cccc990a07f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/856b1da953e46281ba61d7c82d337072d3ee1825", - "reference": "856b1da953e46281ba61d7c82d337072d3ee1825", + "url": "https://api.github.com/repos/illuminate/collections/zipball/705a4e1ef93cd492c45b9b3e7911cccc990a07f4", + "reference": "705a4e1ef93cd492c45b9b3e7911cccc990a07f4", "shasum": "" }, "require": { - "illuminate/conditionable": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "php": "^8.2" + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "php": "^7.3|^8.0" }, "suggest": { - "symfony/var-dumper": "Required to use the dump method (^7.0)." + "symfony/var-dumper": "Required to use the dump method (^5.4)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { "files": [ - "functions.php", "helpers.php" ], "psr-4": { @@ -1765,77 +1593,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" - }, - { - "name": "illuminate/conditionable", - "version": "v11.47.0", - "source": { - "type": "git", - "url": "https://github.com/illuminate/conditionable.git", - "reference": "319b717e0587bd7c8a3b44464f0e27867b4bcda9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/illuminate/conditionable/zipball/319b717e0587bd7c8a3b44464f0e27867b4bcda9", - "reference": "319b717e0587bd7c8a3b44464f0e27867b4bcda9", - "shasum": "" - }, - "require": { - "php": "^8.0.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Illuminate\\Support\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "The Illuminate Conditionable package.", - "homepage": "https://laravel.com", - "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" - }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-06-23T15:29:49+00:00" }, { "name": "illuminate/config", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", - "reference": "64daa8d520cd76e505a82460a672692c56a07be8" + "reference": "feac56ab7a5c70cf2dc60dffe4323eb9851f51a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/config/zipball/64daa8d520cd76e505a82460a672692c56a07be8", - "reference": "64daa8d520cd76e505a82460a672692c56a07be8", + "url": "https://api.github.com/repos/illuminate/config/zipball/feac56ab7a5c70cf2dc60dffe4323eb9851f51a8", + "reference": "feac56ab7a5c70cf2dc60dffe4323eb9851f51a8", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "php": "^8.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1859,49 +1641,43 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-11-14T17:17:02+00:00" + "time": "2022-01-31T15:57:46+00:00" }, { "name": "illuminate/console", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/console.git", - "reference": "a41fbfc99bac948ee27fc8d99bb0e5b4175dec00" + "reference": "4aaa93223eb3bd8119157c95f58c022967826035" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/console/zipball/a41fbfc99bac948ee27fc8d99bb0e5b4175dec00", - "reference": "a41fbfc99bac948ee27fc8d99bb0e5b4175dec00", + "url": "https://api.github.com/repos/illuminate/console/zipball/4aaa93223eb3bd8119157c95f58c022967826035", + "reference": "4aaa93223eb3bd8119157c95f58c022967826035", "shasum": "" }, "require": { - "ext-mbstring": "*", - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "illuminate/view": "^11.0", - "laravel/prompts": "^0.1.20|^0.2|^0.3", - "nunomaduro/termwind": "^2.0", - "php": "^8.2", - "symfony/console": "^7.0.3", - "symfony/polyfill-php83": "^1.31", - "symfony/process": "^7.0.3" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "symfony/console": "^5.4", + "symfony/process": "^5.4" }, "suggest": { - "dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).", - "ext-pcntl": "Required to use signal trapping.", - "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^11.0).", - "illuminate/container": "Required to use the scheduler (^11.0).", - "illuminate/filesystem": "Required to use the generator command (^11.0).", - "illuminate/queue": "Required to use closures for scheduled jobs (^11.0)." + "dragonmantank/cron-expression": "Required to use scheduler (^3.0.2).", + "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.5.5|^7.0.1).", + "illuminate/bus": "Required to use the scheduled job dispatcher (^8.0).", + "illuminate/container": "Required to use the scheduler (^8.0).", + "illuminate/filesystem": "Required to use the generator command (^8.0).", + "illuminate/queue": "Required to use closures for scheduled jobs (^8.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1925,34 +1701,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-11T13:49:37+00:00" + "time": "2022-04-21T22:14:18+00:00" }, { "name": "illuminate/container", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a" + "reference": "14062628d05f75047c5a1360b9350028427d568e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a", - "reference": "79bf9149ad7ddd7e14326ebcdd41197d2c4ee36a", + "url": "https://api.github.com/repos/illuminate/container/zipball/14062628d05f75047c5a1360b9350028427d568e", + "reference": "14062628d05f75047c5a1360b9350028427d568e", "shasum": "" }, "require": { - "illuminate/contracts": "^11.0", - "php": "^8.2", - "psr/container": "^1.1.1|^2.0.1" + "illuminate/contracts": "^8.0", + "php": "^7.3|^8.0", + "psr/container": "^1.0" }, "provide": { - "psr/container-implementation": "1.1|2.0" + "psr/container-implementation": "1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -1976,31 +1752,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-02-02T21:03:35+00:00" }, { "name": "illuminate/contracts", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "4787042340aae19a7ea0fa82f4073c4826204a48" + "reference": "5e0fd287a1b22a6b346a9f7cd484d8cf0234585d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/4787042340aae19a7ea0fa82f4073c4826204a48", - "reference": "4787042340aae19a7ea0fa82f4073c4826204a48", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/5e0fd287a1b22a6b346a9f7cd484d8cf0234585d", + "reference": "5e0fd287a1b22a6b346a9f7cd484d8cf0234585d", "shasum": "" }, "require": { - "php": "^8.2", - "psr/container": "^1.1.1|^2.0.1", - "psr/simple-cache": "^1.0|^2.0|^3.0" + "php": "^7.3|^8.0", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2024,46 +1800,45 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-27T16:16:07+00:00" + "time": "2022-01-13T14:47:47+00:00" }, { "name": "illuminate/database", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "96abcce13f405701363d916dd312835e04848d04" + "reference": "1a5b0e4e6913415464fa2aab554a38b9e6fa44b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/96abcce13f405701363d916dd312835e04848d04", - "reference": "96abcce13f405701363d916dd312835e04848d04", + "url": "https://api.github.com/repos/illuminate/database/zipball/1a5b0e4e6913415464fa2aab554a38b9e6fa44b1", + "reference": "1a5b0e4e6913415464fa2aab554a38b9e6fa44b1", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", - "ext-pdo": "*", - "illuminate/collections": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "laravel/serializable-closure": "^1.3|^2.0", - "php": "^8.2" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "symfony/console": "^5.4" }, "suggest": { - "ext-filter": "Required to use the Postgres database driver.", - "fakerphp/faker": "Required to use the eloquent factory builder (^1.24).", - "illuminate/console": "Required to use the database commands (^11.0).", - "illuminate/events": "Required to use the observers with Eloquent (^11.0).", - "illuminate/filesystem": "Required to use the migrations (^11.0).", - "illuminate/pagination": "Required to paginate the result set (^11.0).", - "symfony/finder": "Required to use Eloquent model factories (^7.0)." + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "illuminate/console": "Required to use the database commands (^8.0).", + "illuminate/events": "Required to use the observers with Eloquent (^8.0).", + "illuminate/filesystem": "Required to use the migrations (^8.0).", + "illuminate/pagination": "Required to paginate the result set (^8.0).", + "symfony/finder": "Required to use Eloquent model factories (^5.4)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2093,34 +1868,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-09-29T09:23:31+00:00" + "time": "2022-08-31T16:16:06+00:00" }, { "name": "illuminate/encryption", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/encryption.git", - "reference": "abd46d355466be65648f1f2503076d204037d699" + "reference": "00280dc6aa204b1b6c6d4bf75936d122bd856c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/encryption/zipball/abd46d355466be65648f1f2503076d204037d699", - "reference": "abd46d355466be65648f1f2503076d204037d699", + "url": "https://api.github.com/repos/illuminate/encryption/zipball/00280dc6aa204b1b6c6d4bf75936d122bd856c15", + "reference": "00280dc6aa204b1b6c6d4bf75936d122bd856c15", "shasum": "" }, "require": { - "ext-hash": "*", + "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "illuminate/contracts": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2144,35 +1919,35 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-06-28T20:15:08+00:00" + "time": "2022-03-14T18:47:47+00:00" }, { "name": "illuminate/events", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", - "reference": "b72dab66d8e05d22dc5aa949efec150bbc73e827" + "reference": "b7f06cafb6c09581617f2ca05d69e9b159e5a35d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/b72dab66d8e05d22dc5aa949efec150bbc73e827", - "reference": "b72dab66d8e05d22dc5aa949efec150bbc73e827", + "url": "https://api.github.com/repos/illuminate/events/zipball/b7f06cafb6c09581617f2ca05d69e9b159e5a35d", + "reference": "b7f06cafb6c09581617f2ca05d69e9b159e5a35d", "shasum": "" }, "require": { - "illuminate/bus": "^11.0", - "illuminate/collections": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/bus": "^8.0", + "illuminate/collections": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2199,53 +1974,48 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2021-09-15T14:32:50+00:00" }, { "name": "illuminate/filesystem", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", - "reference": "d1f217b75ee193bbe27f31df8a94ff6759f31469" + "reference": "73db3e9a233ed587ba54f52ab8580f3c7bc872b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/filesystem/zipball/d1f217b75ee193bbe27f31df8a94ff6759f31469", - "reference": "d1f217b75ee193bbe27f31df8a94ff6759f31469", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/73db3e9a233ed587ba54f52ab8580f3c7bc872b2", + "reference": "73db3e9a233ed587ba54f52ab8580f3c7bc872b2", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2", - "symfony/finder": "^7.0.3" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "symfony/finder": "^5.4" }, "suggest": { - "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", - "ext-hash": "Required to use the Filesystem class.", "illuminate/http": "Required for handling uploaded files (^7.0).", - "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", - "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", - "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.1).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", - "symfony/mime": "Required to enable support for guessing extensions (^7.0)." + "symfony/filesystem": "Required to enable support for relative symbolic links (^5.4).", + "symfony/mime": "Required to enable support for guessing extensions (^5.4)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { - "files": [ - "functions.php" - ], "psr-4": { "Illuminate\\Filesystem\\": "" } @@ -2266,31 +2036,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-01-15T15:00:40+00:00" }, { "name": "illuminate/hashing", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/hashing.git", - "reference": "5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93" + "reference": "2617f4de8d0150a3f8641b086fafac8c1e0cdbf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/hashing/zipball/5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93", - "reference": "5022fe562a5ee1ef9353eeacb1b2b47e8f9dbd93", + "url": "https://api.github.com/repos/illuminate/hashing/zipball/2617f4de8d0150a3f8641b086fafac8c1e0cdbf2", + "reference": "2617f4de8d0150a3f8641b086fafac8c1e0cdbf2", "shasum": "" }, "require": { - "illuminate/contracts": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2314,44 +2084,41 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-14T15:36:00+00:00" + "time": "2021-10-22T13:20:42+00:00" }, { "name": "illuminate/http", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/http.git", - "reference": "b2c744c2dedc1d39b3d5ea6b85232de086f84351" + "reference": "38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/http/zipball/b2c744c2dedc1d39b3d5ea6b85232de086f84351", - "reference": "b2c744c2dedc1d39b3d5ea6b85232de086f84351", + "url": "https://api.github.com/repos/illuminate/http/zipball/38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4", + "reference": "38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4", "shasum": "" }, "require": { - "ext-filter": "*", - "fruitcake/php-cors": "^1.3", - "guzzlehttp/guzzle": "^7.8.2", - "guzzlehttp/uri-template": "^1.0", - "illuminate/collections": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/session": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2", - "symfony/http-foundation": "^7.0.3", - "symfony/http-kernel": "^7.0.3", - "symfony/mime": "^7.0.3", - "symfony/polyfill-php83": "^1.31" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/session": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "symfony/http-foundation": "^5.4", + "symfony/http-kernel": "^5.4", + "symfony/mime": "^5.4" }, "suggest": { - "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image()." + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "guzzlehttp/guzzle": "Required to use the HTTP Client (^6.5.5|^7.0.1)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2375,36 +2142,32 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-17T22:04:40+00:00" + "time": "2022-06-10T18:50:29+00:00" }, { "name": "illuminate/log", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/log.git", - "reference": "73bcd8423739c751442b7e618153c73f78e844cd" + "reference": "1dbdc6aca24d1d2b5903f865bb206039d4b800b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/log/zipball/73bcd8423739c751442b7e618153c73f78e844cd", - "reference": "73bcd8423739c751442b7e618153c73f78e844cd", + "url": "https://api.github.com/repos/illuminate/log/zipball/1dbdc6aca24d1d2b5903f865bb206039d4b800b2", + "reference": "1dbdc6aca24d1d2b5903f865bb206039d4b800b2", "shasum": "" }, "require": { - "illuminate/contracts": "^11.0", - "illuminate/support": "^11.0", - "monolog/monolog": "^3.0", - "php": "^8.2", - "psr/log": "^1.0|^2.0|^3.0" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "monolog/monolog": "^2.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2428,29 +2191,29 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-01-10T15:22:22+00:00" }, { "name": "illuminate/macroable", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", - "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed" + "reference": "aed81891a6e046fdee72edd497f822190f61c162" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/macroable/zipball/e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", - "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/aed81891a6e046fdee72edd497f822190f61c162", + "reference": "aed81891a6e046fdee72edd497f822190f61c162", "shasum": "" }, "require": { - "php": "^8.2" + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2474,33 +2237,33 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-06-28T20:10:30+00:00" + "time": "2021-11-16T13:57:03+00:00" }, { "name": "illuminate/pagination", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/pagination.git", - "reference": "2c4970463f7ede55be207fbdc27608b4c4178380" + "reference": "16fe8dc35f9d18c58a3471469af656a02e9ab692" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/pagination/zipball/2c4970463f7ede55be207fbdc27608b4c4178380", - "reference": "2c4970463f7ede55be207fbdc27608b4c4178380", + "url": "https://api.github.com/repos/illuminate/pagination/zipball/16fe8dc35f9d18c58a3471469af656a02e9ab692", + "reference": "16fe8dc35f9d18c58a3471469af656a02e9ab692", "shasum": "" }, "require": { - "ext-filter": "*", - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2524,31 +2287,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-14T15:33:00+00:00" + "time": "2022-06-27T13:26:06+00:00" }, { "name": "illuminate/pipeline", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/pipeline.git", - "reference": "f73bb7cab13ac8ef91094dc46976f5e992eea127" + "reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/pipeline/zipball/f73bb7cab13ac8ef91094dc46976f5e992eea127", - "reference": "f73bb7cab13ac8ef91094dc46976f5e992eea127", + "url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2", + "reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2", "shasum": "" }, "require": { - "illuminate/contracts": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2572,50 +2335,49 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2021-03-26T18:39:16+00:00" }, { "name": "illuminate/queue", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/queue.git", - "reference": "99218fcdd5efdc0e2c306d4585eb46d9181cf2da" + "reference": "0023daabf67743f7a2bd8328ca2b5537d93e4ae7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/queue/zipball/99218fcdd5efdc0e2c306d4585eb46d9181cf2da", - "reference": "99218fcdd5efdc0e2c306d4585eb46d9181cf2da", + "url": "https://api.github.com/repos/illuminate/queue/zipball/0023daabf67743f7a2bd8328ca2b5537d93e4ae7", + "reference": "0023daabf67743f7a2bd8328ca2b5537d93e4ae7", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/console": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/database": "^11.0", - "illuminate/filesystem": "^11.0", - "illuminate/pipeline": "^11.0", - "illuminate/support": "^11.0", - "laravel/serializable-closure": "^1.3|^2.0", - "php": "^8.2", - "ramsey/uuid": "^4.7", - "symfony/process": "^7.0.3" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/console": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/database": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/support": "^8.0", + "laravel/serializable-closure": "^1.0", + "opis/closure": "^3.6", + "php": "^7.3|^8.0", + "ramsey/uuid": "^4.2.2", + "symfony/process": "^5.4" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.322.9).", - "ext-filter": "Required to use the SQS queue worker.", - "ext-mbstring": "Required to use the database failed job providers.", + "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.198.1).", "ext-pcntl": "Required to use all features of the queue worker.", - "ext-pdo": "Required to use the database queue worker.", "ext-posix": "Required to use all features of the queue worker.", - "illuminate/redis": "Required to use the Redis queue driver (^11.0).", - "pda/pheanstalk": "Required to use the Beanstalk queue driver (^5.0)." + "illuminate/redis": "Required to use the Redis queue driver (^8.0).", + "pda/pheanstalk": "Required to use the Beanstalk queue driver (^4.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2639,40 +2401,39 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-07-01T15:36:47+00:00" + "time": "2022-07-21T19:36:12+00:00" }, { "name": "illuminate/session", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/session.git", - "reference": "00a36b354c12a414236218c1ad193c445b36a191" + "reference": "9c9988d7229d888c098eebbbb9fcb8c68580411c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/session/zipball/00a36b354c12a414236218c1ad193c445b36a191", - "reference": "00a36b354c12a414236218c1ad193c445b36a191", + "url": "https://api.github.com/repos/illuminate/session/zipball/9c9988d7229d888c098eebbbb9fcb8c68580411c", + "reference": "9c9988d7229d888c098eebbbb9fcb8c68580411c", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-session": "*", - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/filesystem": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2", - "symfony/finder": "^7.0.3", - "symfony/http-foundation": "^7.0.3" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0", + "symfony/finder": "^5.4", + "symfony/http-foundation": "^5.4" }, "suggest": { - "illuminate/console": "Required to use the session:table command (^11.0)." + "illuminate/console": "Required to use the session:table command (^8.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2696,61 +2457,52 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-01-13T18:28:06+00:00" }, { "name": "illuminate/support", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "20fbd9f9f502a55de0cbba3f3f81444b7c44af4b" + "reference": "1c79242468d3bbd9a0f7477df34f9647dde2a09b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/20fbd9f9f502a55de0cbba3f3f81444b7c44af4b", - "reference": "20fbd9f9f502a55de0cbba3f3f81444b7c44af4b", + "url": "https://api.github.com/repos/illuminate/support/zipball/1c79242468d3bbd9a0f7477df34f9647dde2a09b", + "reference": "1c79242468d3bbd9a0f7477df34f9647dde2a09b", "shasum": "" }, "require": { - "doctrine/inflector": "^2.0", - "ext-ctype": "*", - "ext-filter": "*", + "doctrine/inflector": "^1.4|^2.0", + "ext-json": "*", "ext-mbstring": "*", - "illuminate/collections": "^11.0", - "illuminate/conditionable": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "nesbot/carbon": "^2.72.6|^3.8.4", - "php": "^8.2", - "voku/portable-ascii": "^2.0.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "nesbot/carbon": "^2.53.1", + "php": "^7.3|^8.0", + "voku/portable-ascii": "^1.6.1" }, "conflict": { "tightenco/collect": "<5.5.33" }, - "replace": { - "spatie/once": "*" - }, "suggest": { - "illuminate/filesystem": "Required to use the Composer class (^11.0).", - "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", - "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).", - "league/uri": "Required to use the Uri class (^7.5.1).", - "ramsey/uuid": "Required to use Str::uuid() (^4.7).", - "symfony/process": "Required to use the Composer class (^7.0).", - "symfony/uid": "Required to use Str::ulid() (^7.0).", - "symfony/var-dumper": "Required to use the dd function (^7.0).", - "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)." + "illuminate/filesystem": "Required to use the composer class (^8.0).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0.2).", + "ramsey/uuid": "Required to use Str::uuid() (^4.2.2).", + "symfony/process": "Required to use the composer class (^5.4).", + "symfony/var-dumper": "Required to use the dd function (^5.4).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { "files": [ - "functions.php", "helpers.php" ], "psr-4": { @@ -2773,42 +2525,41 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-27T16:16:32+00:00" + "time": "2022-09-21T21:30:03+00:00" }, { "name": "illuminate/testing", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/testing.git", - "reference": "cd8b8c5c938be790955a97147b2d999728dcd8bc" + "reference": "1c9ec9902df3b7a38b983bbf2242ce3c088de400" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/testing/zipball/cd8b8c5c938be790955a97147b2d999728dcd8bc", - "reference": "cd8b8c5c938be790955a97147b2d999728dcd8bc", + "url": "https://api.github.com/repos/illuminate/testing/zipball/1c9ec9902df3b7a38b983bbf2242ce3c088de400", + "reference": "1c9ec9902df3b7a38b983bbf2242ce3c088de400", "shasum": "" }, "require": { - "ext-mbstring": "*", - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "suggest": { - "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", - "illuminate/console": "Required to assert console commands (^11.0).", - "illuminate/database": "Required to assert databases (^11.0).", - "illuminate/http": "Required to assert responses (^11.0).", - "mockery/mockery": "Required to use mocking (^1.6).", - "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1)." + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "illuminate/console": "Required to assert console commands (^8.0).", + "illuminate/database": "Required to assert databases (^8.0).", + "illuminate/http": "Required to assert responses (^8.0).", + "mockery/mockery": "Required to use mocking (^1.4.4).", + "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2832,34 +2583,35 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-09-01T02:19:50+00:00" + "time": "2022-05-24T14:00:18+00:00" }, { "name": "illuminate/translation", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/translation.git", - "reference": "de64584470b1d4bfc30f2c291585b873ce844ecf" + "reference": "e119d1e55351bd846579c333dd24f9a042b724b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/translation/zipball/de64584470b1d4bfc30f2c291585b873ce844ecf", - "reference": "de64584470b1d4bfc30f2c291585b873ce844ecf", + "url": "https://api.github.com/repos/illuminate/translation/zipball/e119d1e55351bd846579c333dd24f9a042b724b2", + "reference": "e119d1e55351bd846579c333dd24f9a042b724b2", "shasum": "" }, "require": { - "illuminate/collections": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/filesystem": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2883,44 +2635,43 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-14T15:47:05+00:00" + "time": "2022-05-02T13:55:33+00:00" }, { "name": "illuminate/validation", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/validation.git", - "reference": "076ebfb5fb60ab862588220688bdce3103287466" + "reference": "bb104f15545a55664755f58a278c7013f835918a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/validation/zipball/076ebfb5fb60ab862588220688bdce3103287466", - "reference": "076ebfb5fb60ab862588220688bdce3103287466", + "url": "https://api.github.com/repos/illuminate/validation/zipball/bb104f15545a55664755f58a278c7013f835918a", + "reference": "bb104f15545a55664755f58a278c7013f835918a", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", - "egulias/email-validator": "^3.2.5|^4.0", - "ext-filter": "*", - "ext-mbstring": "*", - "illuminate/collections": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "illuminate/translation": "^11.0", - "php": "^8.2", - "symfony/http-foundation": "^7.0", - "symfony/mime": "^7.0" + "egulias/email-validator": "^2.1.10", + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "illuminate/translation": "^8.0", + "php": "^7.3|^8.0", + "symfony/http-foundation": "^5.4", + "symfony/mime": "^5.4" }, "suggest": { - "illuminate/database": "Required to use the database presence verifier (^11.0)." + "ext-bcmath": "Required to use the multiple_of validation rule.", + "illuminate/database": "Required to use the database presence verifier (^8.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2944,37 +2695,37 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-09-02T23:55:36+00:00" + "time": "2022-05-30T13:21:10+00:00" }, { "name": "illuminate/view", - "version": "v11.47.0", + "version": "v8.83.27", "source": { "type": "git", "url": "https://github.com/illuminate/view.git", - "reference": "9da5543dccb4e406f98016bac8678c97b7dc6915" + "reference": "5e73eef48d9242532f81fadc14c816a01bfb1388" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/view/zipball/9da5543dccb4e406f98016bac8678c97b7dc6915", - "reference": "9da5543dccb4e406f98016bac8678c97b7dc6915", + "url": "https://api.github.com/repos/illuminate/view/zipball/5e73eef48d9242532f81fadc14c816a01bfb1388", + "reference": "5e73eef48d9242532f81fadc14c816a01bfb1388", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "illuminate/collections": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/events": "^11.0", - "illuminate/filesystem": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2" + "ext-json": "*", + "illuminate/collections": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/events": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -2998,34 +2749,34 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-24T11:54:20+00:00" + "time": "2022-04-14T13:47:10+00:00" }, { "name": "jobcloud/php-kafka-lib", - "version": "v2.0.0", + "version": "v1.7.1", "source": { "type": "git", "url": "https://github.com/jobcloud/php-kafka-lib.git", - "reference": "d66de3f984786cf48cca2afbbae4744281747277" + "reference": "2bb7f9c7b771786f37e6f38a168423f480894292" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jobcloud/php-kafka-lib/zipball/d66de3f984786cf48cca2afbbae4744281747277", - "reference": "d66de3f984786cf48cca2afbbae4744281747277", + "url": "https://api.github.com/repos/jobcloud/php-kafka-lib/zipball/2bb7f9c7b771786f37e6f38a168423f480894292", + "reference": "2bb7f9c7b771786f37e6f38a168423f480894292", "shasum": "" }, "require": { "ext-json": "*", "ext-rdkafka": "^4.0|^5.0|^6.0", - "php": "^8.0" + "php": "^7.3|^8.0" }, "require-dev": { "flix-tech/avro-serde-php": "^1.4", - "infection/infection": "^0.26", + "infection/infection": "^0.22", "johnkary/phpunit-speedtrap": "^3.1", "kwn/php-rdkafka-stubs": "^2.0.0", "php-mock/php-mock-phpunit": "^2.6", - "phpstan/phpstan": "^1.8", + "phpstan/phpstan": "^0.12", "phpunit/phpunit": "^9.4", "rregeer/phpunit-coverage-check": "^0.3.1", "squizlabs/php_codesniffer": "^3.5.4" @@ -3063,76 +2814,74 @@ ], "support": { "issues": "https://github.com/jobcloud/php-kafka-lib/issues", - "source": "https://github.com/jobcloud/php-kafka-lib/tree/v2.0.0" + "source": "https://github.com/jobcloud/php-kafka-lib/tree/v1.7.1" }, - "time": "2022-12-30T09:21:59+00:00" + "time": "2022-12-07T08:12:08+00:00" }, { "name": "laravel/lumen-framework", - "version": "v11.2.0", + "version": "v8.3.4", "source": { "type": "git", "url": "https://github.com/laravel/lumen-framework.git", - "reference": "4eb662c94101689c42e48dd395d8f340baefbcac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/4eb662c94101689c42e48dd395d8f340baefbcac", - "reference": "4eb662c94101689c42e48dd395d8f340baefbcac", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.2", - "dragonmantank/cron-expression": "^3.1", - "illuminate/auth": "^11.0", - "illuminate/broadcasting": "^11.0", - "illuminate/bus": "^11.0", - "illuminate/cache": "^11.0", - "illuminate/collections": "^11.0", - "illuminate/config": "^11.0", - "illuminate/console": "^11.0", - "illuminate/container": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/database": "^11.0", - "illuminate/encryption": "^11.0", - "illuminate/events": "^11.0", - "illuminate/filesystem": "^11.0", - "illuminate/hashing": "^11.0", - "illuminate/http": "^11.0", - "illuminate/log": "^11.0", - "illuminate/macroable": "^11.0", - "illuminate/pagination": "^11.0", - "illuminate/pipeline": "^11.0", - "illuminate/queue": "^11.0", - "illuminate/support": "^11.0", - "illuminate/testing": "^11.0", - "illuminate/translation": "^11.0", - "illuminate/validation": "^11.0", - "illuminate/view": "^11.0", - "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "reference": "733d1199d3344be337743f11df31b4048ec7fd1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/733d1199d3344be337743f11df31b4048ec7fd1c", + "reference": "733d1199d3344be337743f11df31b4048ec7fd1c", + "shasum": "" + }, + "require": { + "dragonmantank/cron-expression": "^3.0.2", + "illuminate/auth": "^8.65", + "illuminate/broadcasting": "^8.65", + "illuminate/bus": "^8.65", + "illuminate/cache": "^8.65", + "illuminate/collections": "^8.65", + "illuminate/config": "^8.65", + "illuminate/console": "^8.65", + "illuminate/container": "^8.65", + "illuminate/contracts": "^8.65", + "illuminate/database": "^8.65", + "illuminate/encryption": "^8.65", + "illuminate/events": "^8.65", + "illuminate/filesystem": "^8.65", + "illuminate/hashing": "^8.65", + "illuminate/http": "^8.65", + "illuminate/log": "^8.65", + "illuminate/macroable": "^8.65", + "illuminate/pagination": "^8.65", + "illuminate/pipeline": "^8.65", + "illuminate/queue": "^8.65", + "illuminate/support": "^8.65", + "illuminate/testing": "^8.65", + "illuminate/translation": "^8.65", + "illuminate/validation": "^8.65", + "illuminate/view": "^8.65", "nikic/fast-route": "^1.3", - "php": "^8.2", - "symfony/console": "^7.0", - "symfony/error-handler": "^7.0", - "symfony/http-foundation": "^7.0", - "symfony/http-kernel": "^7.0", - "symfony/mime": "^7.0", - "symfony/var-dumper": "^7.0", - "vlucas/phpdotenv": "^5.4.1" + "php": "^7.3|^8.0", + "symfony/console": "^5.4", + "symfony/error-handler": "^5.4", + "symfony/http-foundation": "^5.4", + "symfony/http-kernel": "^5.4", + "symfony/mime": "^5.4", + "symfony/var-dumper": "^5.4", + "vlucas/phpdotenv": "^5.2" }, "require-dev": { - "mockery/mockery": "^1.6.10", - "phpunit/phpunit": "^10.5.35" + "mockery/mockery": "^1.4.4", + "phpunit/phpunit": "^8.5.19|^9.5.8" }, "suggest": { - "laravel/tinker": "Required to use the tinker console command (^2.7).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { @@ -3164,95 +2913,36 @@ "issues": "https://github.com/laravel/lumen-framework/issues", "source": "https://github.com/laravel/lumen-framework" }, - "time": "2024-11-26T15:27:28+00:00" + "time": "2021-12-22T10:11:35+00:00" }, { - "name": "laravel/prompts", - "version": "v0.3.10", + "name": "laravel/serializable-closure", + "version": "v1.3.7", "source": { "type": "git", - "url": "https://github.com/laravel/prompts.git", - "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3" + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/360ba095ef9f51017473505191fbd4ab73e1cab3", - "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d", + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d", "shasum": "" }, "require": { - "composer-runtime-api": "^2.2", - "ext-mbstring": "*", - "php": "^8.1", - "symfony/console": "^6.2|^7.0" - }, - "conflict": { - "illuminate/console": ">=10.17.0 <10.25.0", - "laravel/framework": ">=10.17.0 <10.25.0" + "php": "^7.3|^8.0" }, "require-dev": { - "illuminate/collections": "^10.0|^11.0|^12.0", - "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4|^4.0", - "phpstan/phpstan": "^1.12.28", - "phpstan/phpstan-mockery": "^1.1.3" - }, - "suggest": { - "ext-pcntl": "Required for the spinner to be animated." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "0.3.x-dev" - } - }, - "autoload": { - "files": [ - "src/helpers.php" - ], - "psr-4": { - "Laravel\\Prompts\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Add beautiful and user-friendly forms to your command-line applications.", - "support": { - "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.10" - }, - "time": "2026-01-13T20:29:29+00:00" - }, - { - "name": "laravel/serializable-closure", - "version": "v2.0.8", - "source": { - "type": "git", - "url": "https://github.com/laravel/serializable-closure.git", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "illuminate/support": "^10.0|^11.0|^12.0", - "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0|^4.0", - "phpstan/phpstan": "^2.0", - "symfony/var-dumper": "^6.2.0|^7.0.0" + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "nesbot/carbon": "^2.61|^3.0", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -3284,7 +2974,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-01-08T16:22:46+00:00" + "time": "2024-11-14T18:34:49+00:00" }, { "name": "league/flysystem", @@ -3438,43 +3128,42 @@ }, { "name": "monolog/monolog", - "version": "3.10.0", + "version": "2.11.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" + "reference": "37308608e599f34a1a4845b16440047ec98a172a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", - "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/37308608e599f34a1a4845b16440047ec98a172a", + "reference": "37308608e599f34a1a4845b16440047ec98a172a", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "3.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2.0", - "guzzlehttp/guzzle": "^7.4.5", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", - "php-console/php-console": "^3.1.8", - "phpstan/phpstan": "^2", - "phpstan/phpstan-deprecation-rules": "^2", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^10.5.17 || ^11.0.7", - "predis/predis": "^1.1 || ^2", - "rollbar/rollbar": "^4.0", - "ruflin/elastica": "^7 || ^8", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.38 || ^9.6.19", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -3497,7 +3186,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -3525,7 +3214,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.10.0" + "source": "https://github.com/Seldaek/monolog/tree/2.11.0" }, "funding": [ { @@ -3537,7 +3226,7 @@ "type": "tidelift" } ], - "time": "2026-01-02T08:56:05+00:00" + "time": "2026-01-01T13:05:00+00:00" }, { "name": "mtdowling/jmespath.php", @@ -3607,40 +3296,42 @@ }, { "name": "nesbot/carbon", - "version": "3.11.0", + "version": "2.73.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1" + "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/9228ce90e1035ff2f0db84b40ec2e023ed802075", + "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "<100.0", + "carbonphp/carbon-doctrine-types": "*", "ext-json": "*", - "php": "^8.1", + "php": "^7.1.8 || ^8.0", "psr/clock": "^1.0", - "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "doctrine/dbal": "^3.6.3 || ^4.0", - "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^v3.87.1", - "kylekatarnls/multi-tester": "^2.5.3", - "phpmd/phpmd": "^2.15.0", - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.22", - "phpunit/phpunit": "^10.5.53", - "squizlabs/php_codesniffer": "^3.13.4" + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "<6", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" }, "bin": [ "bin/carbon" @@ -3691,8 +3382,8 @@ ], "support": { "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/CarbonPHP/carbon/issues", - "source": "https://github.com/CarbonPHP/carbon" + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" }, "funding": [ { @@ -3708,7 +3399,7 @@ "type": "tidelift" } ], - "time": "2025-12-02T21:04:28+00:00" + "time": "2025-01-08T20:10:23+00:00" }, { "name": "nikic/fast-route", @@ -3761,51 +3452,38 @@ "time": "2018-02-13T20:26:39+00:00" }, { - "name": "nunomaduro/termwind", - "version": "v2.3.3", + "name": "opis/closure", + "version": "3.7.0", "source": { "type": "git", - "url": "https://github.com/nunomaduro/termwind.git", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" + "url": "https://github.com/opis/closure.git", + "reference": "b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "url": "https://api.github.com/repos/opis/closure/zipball/b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4", + "reference": "b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": "^8.2", - "symfony/console": "^7.3.6" + "php": "^5.4 || ^7.0 || ^8.0" }, "require-dev": { - "illuminate/console": "^11.46.1", - "laravel/pint": "^1.25.1", - "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", - "phpstan/phpstan": "^1.12.32", - "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.3.5", - "thecodingmachine/phpstan-strict-rules": "^1.0.0" + "jeremeamia/superclosure": "^2.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { - "laravel": { - "providers": [ - "Termwind\\Laravel\\TermwindServiceProvider" - ] - }, "branch-alias": { - "dev-2.x": "2.x-dev" + "dev-master": "3.6.x-dev" } }, "autoload": { "files": [ - "src/Functions.php" + "functions.php" ], "psr-4": { - "Termwind\\": "src/" + "Opis\\Closure\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3814,38 +3492,29 @@ ], "authors": [ { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" } ], - "description": "Its like Tailwind CSS, but for the console.", + "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", + "homepage": "https://opis.io/closure", "keywords": [ - "cli", - "console", - "css", - "package", - "php", - "style" + "anonymous functions", + "closure", + "function", + "serializable", + "serialization", + "serialize" ], "support": { - "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" + "issues": "https://github.com/opis/closure/issues", + "source": "https://github.com/opis/closure/tree/3.7.0" }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://github.com/xiCO2k", - "type": "github" - } - ], - "time": "2025-11-20T02:34:59+00:00" + "time": "2025-07-08T20:30:08+00:00" }, { "name": "phpoption/phpoption", @@ -3972,27 +3641,22 @@ }, { "name": "psr/container", - "version": "2.0.2", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -4019,9 +3683,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/event-dispatcher", @@ -4235,16 +3899,16 @@ }, { "name": "psr/log", - "version": "3.0.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", "shasum": "" }, "require": { @@ -4253,7 +3917,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4279,31 +3943,31 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" + "source": "https://github.com/php-fig/log/tree/2.0.0" }, - "time": "2024-09-11T13:17:53+00:00" + "time": "2021-07-14T16:41:46+00:00" }, { "name": "psr/simple-cache", - "version": "3.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -4318,7 +3982,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -4330,9 +3994,9 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + "source": "https://github.com/php-fig/simple-cache/tree/master" }, - "time": "2021-10-29T13:26:27+00:00" + "time": "2017-10-23T01:57:42+00:00" }, { "name": "ralouphie/getallheaders", @@ -4380,39 +4044,43 @@ }, { "name": "ramsey/collection", - "version": "2.1.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", - "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.4 || ^8.0", + "symfony/polyfill-php81": "^1.23" }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.45", - "fakerphp/faker": "^1.24", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^2.1", - "mockery/mockery": "^1.6", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.4", - "phpspec/prophecy-phpunit": "^2.3", - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-mockery": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^10.5", - "ramsey/coding-standard": "^2.3", - "ramsey/conventional-commits": "^1.6", - "roave/security-advisories": "dev-latest" + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" }, "type": "library", "extra": { @@ -4450,9 +4118,19 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.1.1" + "source": "https://github.com/ramsey/collection/tree/1.3.0" }, - "time": "2025-03-22T05:38:12+00:00" + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-27T19:12:24+00:00" }, { "name": "ramsey/uuid", @@ -4532,127 +4210,54 @@ }, "time": "2025-12-14T04:43:48+00:00" }, - { - "name": "symfony/clock", - "version": "v7.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/clock.git", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/now.php" - ], - "psr-4": { - "Symfony\\Component\\Clock\\": "" - }, - "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": "Decouples applications from the system clock", - "homepage": "https://symfony.com", - "keywords": [ - "clock", - "psr20", - "time" - ], - "support": { - "source": "https://github.com/symfony/clock/tree/v7.4.0" - }, - "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-11-12T15:39:26+00:00" - }, { "name": "symfony/console", - "version": "v7.4.3", + "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2|^8.0" + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" }, "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" }, "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/lock": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, "type": "library", "autoload": { @@ -4686,7 +4291,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.3" + "source": "https://github.com/symfony/console/tree/v5.4.47" }, "funding": [ { @@ -4697,33 +4302,29 @@ "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-12-23T14:50:43+00:00" + "time": "2024-11-06T11:30:55+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "type": "library", "extra": { @@ -4732,7 +4333,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -4757,7 +4358,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -4773,38 +4374,31 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/error-handler", - "version": "v7.4.0", + "version": "v5.4.46", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d19ede7a2cafb386be9486c580649d0f9e3d0363", + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=7.2.5", "psr/log": "^1|^2|^3", - "symfony/polyfill-php85": "^1.32", - "symfony/var-dumper": "^6.4|^7.0|^8.0" - }, - "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", - "symfony/webpack-encore-bundle": "^1.0|^2.0" + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/serializer": "^4.4|^5.0|^6.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4835,7 +4429,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.0" + "source": "https://github.com/symfony/error-handler/tree/v5.4.46" }, "funding": [ { @@ -4846,38 +4440,33 @@ "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-11-05T14:29:59+00:00" + "time": "2024-11-05T14:17:06+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.0", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d" + "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", + "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/event-dispatcher-contracts": "^2.5|^3" + "php": ">=8.0.2", + "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/service-contracts": "<2.5" + "symfony/dependency-injection": "<5.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -4885,14 +4474,17 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/framework-bundle": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0|^8.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "autoload": { @@ -4920,7 +4512,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.19" }, "funding": [ { @@ -4931,35 +4523,34 @@ "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-10-28T09:38:46+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/event-dispatcher": "^1" }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, "type": "library", "extra": { "thanks": { @@ -4967,7 +4558,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -5000,73 +4591,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-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/filesystem", - "version": "v7.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" }, "funding": [ { @@ -5077,36 +4602,31 @@ "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-11-27T13:27:24+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/finder", - "version": "v7.4.3", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06" + "reference": "63741784cd7b9967975eec610b256eed3ede022b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06", + "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", + "reference": "63741784cd7b9967975eec610b256eed3ede022b", "shasum": "" }, "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -5134,7 +4654,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.3" + "source": "https://github.com/symfony/finder/tree/v5.4.45" }, "funding": [ { @@ -5145,50 +4665,44 @@ "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-12-23T14:50:43+00:00" + "time": "2024-09-28T13:32:08+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.3", + "version": "v5.4.50", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52" + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1a0706e8b8041046052ea2695eb8aeee04f97609", + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "^1.1" - }, - "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/rate-limiter": "^6.4|^7.0|^8.0" + "predis/predis": "^1.0|^2.0", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" }, "type": "library", "autoload": { @@ -5216,7 +4730,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.3" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.50" }, "funding": [ { @@ -5236,78 +4750,76 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:23:49+00:00" + "time": "2025-11-03T12:58:48+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.3", + "version": "v5.4.51", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "885211d4bed3f857b8c964011923528a55702aa5" + "reference": "85432f7548b2757b8387f7e1a468abd62fc4c9bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5", - "reference": "885211d4bed3f857b8c964011923528a55702aa5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/85432f7548b2757b8387f7e1a468abd62fc4c9bc", + "reference": "85432f7548b2757b8387f7e1a468abd62fc4c9bc", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^7.3|^8.0", - "symfony/http-foundation": "^7.4|^8.0", - "symfony/polyfill-ctype": "^1.8" + "php": ">=7.2.5", + "psr/log": "^1|^2", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^5.0|^6.0", + "symfony/http-foundation": "^5.4.21|^6.2.7", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/flex": "<2.10", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/console": "<4.4", + "symfony/dependency-injection": "<5.3", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.13" }, "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/dom-crawler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^7.1|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/serializer": "^7.1|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "symfony/browser-kit": "^5.4|^6.0", + "symfony/config": "^5.0|^6.0", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.3|^6.0", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/translation": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/var-dumper": "^4.4.31|^5.4", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" }, "type": "library", "autoload": { @@ -5335,7 +4847,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.3" + "source": "https://github.com/symfony/http-kernel/tree/v5.4.51" }, "funding": [ { @@ -5355,44 +4867,44 @@ "type": "tidelift" } ], - "time": "2025-12-31T08:43:57+00:00" + "time": "2026-01-28T07:10:35+00:00" }, { "name": "symfony/mime", - "version": "v7.4.0", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<6.4", - "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + "symfony/mailer": "<4.4", + "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4.3|^7.0.3|^8.0" + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/process": "^5.4|^6.4", + "symfony/property-access": "^4.4|^5.1|^6.0", + "symfony/property-info": "^4.4|^5.1|^6.0", + "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3" }, "type": "library", "autoload": { @@ -5424,7 +4936,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.0" + "source": "https://github.com/symfony/mime/tree/v5.4.45" }, "funding": [ { @@ -5435,16 +4947,12 @@ "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-11-16T10:14:42+00:00" + "time": "2024-10-23T20:18:32+00:00" }, { "name": "symfony/polyfill-ctype", @@ -5869,17 +5377,17 @@ "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/polyfill-php80", + "name": "symfony/polyfill-php73", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { @@ -5897,7 +5405,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php73\\": "" }, "classmap": [ "Resources/stubs" @@ -5908,10 +5416,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -5921,7 +5425,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -5930,7 +5434,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" }, "funding": [ { @@ -5950,20 +5454,20 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php83", + "name": "symfony/polyfill-php80", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -5981,7 +5485,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -5992,6 +5496,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -6001,7 +5509,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -6010,7 +5518,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -6030,20 +5538,20 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/polyfill-php85", + "name": "symfony/polyfill-php81", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { @@ -6061,7 +5569,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php85\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -6081,7 +5589,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -6090,7 +5598,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -6110,24 +5618,25 @@ "type": "tidelift" } ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v7.4.3", + "version": "v5.4.51", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f" + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f", - "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f", + "url": "https://api.github.com/repos/symfony/process/zipball/467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -6155,7 +5664,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.3" + "source": "https://github.com/symfony/process/tree/v5.4.51" }, "funding": [ { @@ -6175,30 +5684,33 @@ "type": "tidelift" } ], - "time": "2025-12-19T10:00:43+00:00" + "time": "2026-01-26T15:53:37+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.1", + "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "type": "library", "extra": { "thanks": { @@ -6206,16 +5718,13 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "2.5-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6242,7 +5751,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" }, "funding": [ { @@ -6253,48 +5762,42 @@ "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" + "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/string", - "version": "v7.4.0", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003" + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", + "php": ">=8.0.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.33", + "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/translation-contracts": "<2.0" }, "require-dev": { - "symfony/emoji": "^7.1|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -6333,7 +5836,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.0" + "source": "https://github.com/symfony/string/tree/v6.0.19" }, "funding": [ { @@ -6344,65 +5847,60 @@ "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-11-27T13:27:24+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/translation", - "version": "v7.4.3", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d" + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/7ef27c65d78886f7599fdd5c93d12c9243ecf44d", - "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d", + "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.0.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5.3|^3.3" + "symfony/translation-contracts": "^2.3|^3.0" }, "conflict": { - "nikic/php-parser": "<5.0", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" }, "type": "library", "autoload": { @@ -6433,7 +5931,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.3" + "source": "https://github.com/symfony/translation/tree/v6.0.19" }, "funding": [ { @@ -6444,33 +5942,32 @@ "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-12-29T09:31:36+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977" + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" + }, + "suggest": { + "symfony/translation-implementation": "" }, "type": "library", "extra": { @@ -6479,16 +5976,13 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6515,7 +6009,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" }, "funding": [ { @@ -6526,45 +6020,47 @@ "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-15T13:41:35+00:00" + "time": "2022-06-27T17:10:44+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.3", + "version": "v5.4.48", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92" + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/console": "<6.4" + "symfony/console": "<4.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, "bin": [ "Resources/bin/var-dump-server" @@ -6602,7 +6098,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.3" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" }, "funding": [ { @@ -6613,16 +6109,12 @@ "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-12-18T07:04:31+00:00" + "time": "2024-11-08T15:21:10+00:00" }, { "name": "vlucas/phpdotenv", @@ -6710,16 +6202,16 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.3", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/87337c91b9dfacee02452244ee14ab3c43bc485a", + "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a", "shasum": "" }, "require": { @@ -6744,7 +6236,7 @@ "authors": [ { "name": "Lars Moelleken", - "homepage": "https://www.moelleken.org/" + "homepage": "http://www.moelleken.org/" } ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", @@ -6756,7 +6248,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "source": "https://github.com/voku/portable-ascii/tree/1.6.1" }, "funding": [ { @@ -6780,7 +6272,7 @@ "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2022-01-24T18:55:24+00:00" }, { "name": "widmogrod/php-functional", @@ -6856,38 +6348,35 @@ "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.2.0", + "version": "v0.7.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", - "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", "shasum": "" }, "require": { - "composer-plugin-api": "^2.2", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "^2.2", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", - "yoast/phpunit-polyfills": "^1.0" + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" }, "type": "composer-plugin", "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -6897,16 +6386,17 @@ "authors": [ { "name": "Franck Nijhof", - "email": "opensource@frenck.dev", - "homepage": "https://frenck.dev", - "role": "Open source developer" + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" }, { "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -6926,56 +6416,37 @@ "tests" ], "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", - "source": "https://github.com/PHPCSStandards/composer-installer" + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2025-11-11T04:32:07+00:00" + "time": "2022-02-04T12:51:07+00:00" }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -7002,7 +6473,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -7018,7 +6489,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -7392,16 +6863,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.1", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { @@ -7433,9 +6904,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2026-01-12T11:33:04+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8074,16 +7545,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.9", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -8136,7 +7607,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { @@ -8156,7 +7627,7 @@ "type": "tidelift" } ], - "time": "2025-08-10T06:51:50+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -8918,32 +8389,32 @@ }, { "name": "slevomat/coding-standard", - "version": "8.26.0", + "version": "8.27.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c" + "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/d247cdc04b91956bdcfaa0b1313c01960b189d3c", - "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/29bdaee8b65e7ed2b8e702b01852edba8bae1769", + "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.0", "php": "^7.4 || ^8.0", - "phpstan/phpdoc-parser": "^2.3.0", + "phpstan/phpdoc-parser": "^2.3.1", "squizlabs/php_codesniffer": "^4.0.1" }, "require-dev": { - "phing/phing": "3.0.1|3.1.0", + "phing/phing": "3.0.1|3.1.1", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.33", + "phpstan/phpstan": "2.1.37", "phpstan/phpstan-deprecation-rules": "2.0.3", - "phpstan/phpstan-phpunit": "2.0.11", + "phpstan/phpstan-phpunit": "2.0.12", "phpstan/phpstan-strict-rules": "2.0.7", - "phpunit/phpunit": "9.6.31|10.5.60|11.4.4|11.5.46|12.5.4" + "phpunit/phpunit": "9.6.31|10.5.60|11.4.4|11.5.49|12.5.7" }, "type": "phpcodesniffer-standard", "extra": { @@ -8967,7 +8438,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.26.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.27.1" }, "funding": [ { @@ -8979,7 +8450,7 @@ "type": "tidelift" } ], - "time": "2025-12-21T18:01:15+00:00" + "time": "2026-01-25T15:57:07+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -9117,8 +8588,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.3" + "php": "^7.3|^8.0" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.0.0" } From d6e9633cb268ba6bcda03e2a9a1a6773a5d3dde2 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 19 Feb 2026 20:34:02 +0700 Subject: [PATCH 40/42] minio storage service provider --- src/Libraries/StorageDrivers/Minio.php | 4 +- src/Providers/MinioStorageServiceProvider.php | 86 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/Providers/MinioStorageServiceProvider.php diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index 701515f..d0d8d58 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -128,9 +128,9 @@ public function securelink(string $filepath): string /** * Illuminate\Filesystem\FilesystemAdapter $disk file storage disk * - * @var \Illuminate\Filesystem\FilesystemAdapter $disk file storage disk + * @var \Spotlibs\PhpLib\Libraries\StorageDrivers\MinioAdapter $disk file storage disk */ - $disk = FacadeStorage::disk($this->driver); + $disk = FacadeStorage::disk($this->driver)->getDriver(); $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds((int) env('MINIO_EXPIRED_URL', 60))); return $urlpath; } diff --git a/src/Providers/MinioStorageServiceProvider.php b/src/Providers/MinioStorageServiceProvider.php new file mode 100644 index 0000000..dc173c9 --- /dev/null +++ b/src/Providers/MinioStorageServiceProvider.php @@ -0,0 +1,86 @@ + + * @license https://mit-license.org/ MIT License + * @version GIT: 0.3.1 + * @link https://github.com/spotlibs + */ + +declare(strict_types=1); + +namespace App\Providers; + +use Aws\S3\S3Client; +use Illuminate\Support\ServiceProvider; +use League\Flysystem\AwsS3v3\AwsS3Adapter; +use Illuminate\Support\Facades\Storage; +use Spotlibs\PhpLib\Libraries\StorageDrivers\MinioAdapter; + +/** + * MinioStorageServiceProvider + * + * Service provider for MinIO storage + * + * @category StandardService + * @package ServiceProvider + * @author Made Mas Adi Winata + * @license https://mit-license.org/ MIT License + * @link https://github.com/spotlibs + */ +class MinioStorageServiceProvider extends ServiceProvider +{ + /** + * Bootstrap the application services. + * + * @return void + */ + public function boot() + { + Storage::extend('minio', function ($app, $config) { + // Client for internal Docker network communication + $client = new S3Client([ + 'credentials' => [ + 'key' => $config["key"], + 'secret' => $config["secret"] + ], + 'region' => $config["region"], + 'version' => "latest", + 'bucket_endpoint' => false, + 'use_path_style_endpoint' => true, + 'endpoint' => $config["endpoint"], // e.g., http://minio:9000 + ]); + + $adapter = new AwsS3Adapter($client, $config["bucket"]); + + // Public client for browser-accessible URLs + $publicClient = new S3Client([ + 'credentials' => [ + 'key' => $config['key'], + 'secret' => $config['secret'] + ], + 'region' => $config['region'], + 'version' => 'latest', + 'use_path_style_endpoint' => true, + 'endpoint' => $config['url'] ?? $config['endpoint'], // e.g., http://localhost:9000 + ]); + + // Return your custom MinioAdapter (which extends Filesystem) + return new MinioAdapter($adapter, $config, $publicClient); + }); + } + + /** + * Register the application services. + * + * @return void + */ + public function register() + { + + } +} From 41d88e5f1f6ba06112b67901a4f3fabf5d152e78 Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 19 Feb 2026 20:38:35 +0700 Subject: [PATCH 41/42] fix namespace --- src/Providers/MinioStorageServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Providers/MinioStorageServiceProvider.php b/src/Providers/MinioStorageServiceProvider.php index dc173c9..ecca2e6 100644 --- a/src/Providers/MinioStorageServiceProvider.php +++ b/src/Providers/MinioStorageServiceProvider.php @@ -13,7 +13,7 @@ declare(strict_types=1); -namespace App\Providers; +namespace Spotlibs\PhpLib\Providers; use Aws\S3\S3Client; use Illuminate\Support\ServiceProvider; From 566385966c40545b71443ba180fa40958956392d Mon Sep 17 00:00:00 2001 From: Made Mas Adi Winata Date: Thu, 19 Feb 2026 20:53:25 +0700 Subject: [PATCH 42/42] adjustment for php8.0 --- src/Libraries/StorageDrivers/Minio.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php index d0d8d58..e79320e 100644 --- a/src/Libraries/StorageDrivers/Minio.php +++ b/src/Libraries/StorageDrivers/Minio.php @@ -151,8 +151,8 @@ public function securelinkFolder(string $dirpath): array $allFiles = FacadeStorage::disk($this->driver)->allFiles($dirpath); $result = []; foreach ($allFiles as $file) { - $filename = parent::getFileName($file["path"]); - $fileStream = FacadeStorage::disk($this->driver)->readStream($file["path"]); + $filename = parent::getFileName($file); + $fileStream = FacadeStorage::disk($this->driver)->readStream($file); $writeStream = fopen($linkFolder . "/" . $filename, 'w'); stream_copy_to_stream($fileStream, $writeStream); fclose($fileStream);