diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index d3446a7..a0e9706 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -17,7 +17,7 @@ jobs:
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
diff --git a/composer.json b/composer.json
index b09991c..0f25c9e 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",
+ "coraxster/flysystem-aws-s3-v3-minio": "^1.0"
},
"autoload": {
"psr-4": {
diff --git a/composer.lock b/composer.lock
index 8f7b75a..41c66b5 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,172 @@
"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": "82c5862031b247e0f468c8d6fca45b62",
"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",
+ "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 +177,7 @@
"ext-json": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
- "php": "^7.0 || ^8.0"
+ "php": "^7.1 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "*",
@@ -69,9 +221,9 @@
],
"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",
@@ -197,35 +349,84 @@
],
"time": "2023-12-11T17:09:12+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.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/",
@@ -270,7 +471,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": [
{
@@ -286,7 +487,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-18T20:23:39+00:00"
+ "time": "2025-08-10T19:31:58+00:00"
},
{
"name": "doctrine/lexer",
@@ -366,29 +567,28 @@
},
{
"name": "dragonmantank/cron-expression",
- "version": "v3.4.0",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
- "reference": "8c784d071debd117328803d86b2097615b457500"
+ "reference": "1b2de7f4a468165dca07b142240733a1973e766d"
},
"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/1b2de7f4a468165dca07b142240733a1973e766d",
+ "reference": "1b2de7f4a468165dca07b142240733a1973e766d",
"shasum": ""
},
"require": {
- "php": "^7.2|^8.0",
- "webmozart/assert": "^1.0"
+ "php": "^7.2|^8.0"
},
"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": {
@@ -419,7 +619,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.5.0"
},
"funding": [
{
@@ -427,7 +627,7 @@
"type": "github"
}
],
- "time": "2024-10-09T13:47:03+00:00"
+ "time": "2025-10-31T18:36:32+00:00"
},
{
"name": "egulias/email-validator",
@@ -574,8 +774,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": {
@@ -685,16 +885,16 @@
},
{
"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,30 +927,30 @@
"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",
- "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": {
@@ -779,7 +979,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": [
{
@@ -791,20 +991,20 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:45:45+00:00"
+ "time": "2025-12-27T19:43:20+00:00"
},
{
"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 +1101,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,7 +1117,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-24T11:22:20+00:00"
+ "time": "2025-03-27T13:37:11+00:00"
},
{
"name": "guzzlehttp/promises",
@@ -1000,16 +1200,16 @@
},
{
"name": "guzzlehttp/psr7",
- "version": "2.7.0",
+ "version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
+ "reference": "21dc724a0583619cd1652f673303492272778051"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
+ "reference": "21dc724a0583619cd1652f673303492272778051",
"shasum": ""
},
"require": {
@@ -1025,7 +1225,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"
@@ -1096,7 +1296,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.8.0"
},
"funding": [
{
@@ -1112,7 +1312,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-18T11:15:46+00:00"
+ "time": "2025-08-23T21:21:41+00:00"
},
{
"name": "illuminate/auth",
@@ -2717,16 +2917,16 @@
},
{
"name": "laravel/serializable-closure",
- "version": "v1.3.5",
+ "version": "v1.3.7",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c"
+ "reference": "4f48ade902b94323ca3be7646db16209ec76be3d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c",
- "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d",
+ "reference": "4f48ade902b94323ca3be7646db16209ec76be3d",
"shasum": ""
},
"require": {
@@ -2774,20 +2974,170 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2024-09-23T13:33:08+00:00"
+ "time": "2024-11-14T18:34:49+00:00"
+ },
+ {
+ "name": "league/flysystem",
+ "version": "1.1.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem.git",
+ "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3239285c825c152bcc315fe0e87d6b55f5972ed1",
+ "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "league/mime-type-detection": "^1.3",
+ "php": "^7.2.5 || ^8.0"
+ },
+ "conflict": {
+ "league/flysystem-sftp": "<1.0.6"
+ },
+ "require-dev": {
+ "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/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frenky.net"
+ }
+ ],
+ "description": "Filesystem abstraction: Many filesystems, one API.",
+ "keywords": [
+ "Cloud Files",
+ "WebDAV",
+ "abstraction",
+ "aws",
+ "cloud",
+ "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/1.1.10"
+ },
+ "funding": [
+ {
+ "url": "https://offset.earth/frankdejonge",
+ "type": "other"
+ }
+ ],
+ "time": "2022-10-04T09:16: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": "2.9.3",
+ "version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215"
+ "reference": "37308608e599f34a1a4845b16440047ec98a172a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/a30bfe2e142720dfa990d0a7e573997f5d884215",
- "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/37308608e599f34a1a4845b16440047ec98a172a",
+ "reference": "37308608e599f34a1a4845b16440047ec98a172a",
"shasum": ""
},
"require": {
@@ -2805,7 +3155,7 @@
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
- "mongodb/mongodb": "^1.8",
+ "mongodb/mongodb": "^1.8 || ^2.0",
"php-amqplib/php-amqplib": "~2.4 || ^3",
"phpspec/prophecy": "^1.15",
"phpstan/phpstan": "^1.10",
@@ -2864,7 +3214,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/2.11.0"
},
"funding": [
{
@@ -2876,20 +3226,86 @@
"type": "tidelift"
}
],
- "time": "2024-04-12T20:52:51+00:00"
+ "time": "2026-01-01T13:05:00+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",
+ "version": "2.73.0",
"source": {
"type": "git",
- "url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed"
+ "url": "https://github.com/CarbonPHP/carbon.git",
+ "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/afd46589c216118ecd48ff2b95d77596af1e57ed",
- "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/9228ce90e1035ff2f0db84b40ec2e023ed802075",
+ "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075",
"shasum": ""
},
"require": {
@@ -2909,7 +3325,7 @@
"doctrine/orm": "^2.7 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
- "ondrejmirtes/better-reflection": "*",
+ "ondrejmirtes/better-reflection": "<6",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.99 || ^1.7.14",
@@ -2922,10 +3338,6 @@
],
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "3.x-dev",
- "dev-2.x": "2.x-dev"
- },
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
@@ -2935,6 +3347,10 @@
"includes": [
"extension.neon"
]
+ },
+ "branch-alias": {
+ "dev-2.x": "2.x-dev",
+ "dev-master": "3.x-dev"
}
},
"autoload": {
@@ -2983,7 +3399,7 @@
"type": "tidelift"
}
],
- "time": "2024-06-03T19:18:41+00:00"
+ "time": "2025-01-08T20:10:23+00:00"
},
{
"name": "nikic/fast-route",
@@ -3037,16 +3453,16 @@
},
{
"name": "opis/closure",
- "version": "3.6.3",
+ "version": "3.7.0",
"source": {
"type": "git",
"url": "https://github.com/opis/closure.git",
- "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad"
+ "reference": "b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad",
- "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad",
+ "url": "https://api.github.com/repos/opis/closure/zipball/b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4",
+ "reference": "b1a22a6be71c1263f3ca6e68f00b3fd4d394abc4",
"shasum": ""
},
"require": {
@@ -3096,22 +3512,22 @@
],
"support": {
"issues": "https://github.com/opis/closure/issues",
- "source": "https://github.com/opis/closure/tree/3.6.3"
+ "source": "https://github.com/opis/closure/tree/3.7.0"
},
- "time": "2022-01-27T09:35:39+00:00"
+ "time": "2025-07-08T20:30:08+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": {
@@ -3119,7 +3535,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": {
@@ -3161,7 +3577,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": [
{
@@ -3173,7 +3589,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:41:07+00:00"
+ "time": "2025-12-27T19:41:33+00:00"
},
{
"name": "psr/clock",
@@ -3718,21 +4134,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"
},
@@ -3740,26 +4155,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.",
@@ -3794,32 +4206,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/console",
- "version": "v5.4.44",
+ "version": "v5.4.47",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "5b5a0aa66e3296e303e22490f90f521551835a83"
+ "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/5b5a0aa66e3296e303e22490f90f521551835a83",
- "reference": "5b5a0aa66e3296e303e22490f90f521551835a83",
+ "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
+ "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
"shasum": ""
},
"require": {
@@ -3889,7 +4291,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v5.4.44"
+ "source": "https://github.com/symfony/console/tree/v5.4.47"
},
"funding": [
{
@@ -3905,7 +4307,7 @@
"type": "tidelift"
}
],
- "time": "2024-09-20T07:56:40+00:00"
+ "time": "2024-11-06T11:30:55+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3926,12 +4328,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "3.0-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -3976,16 +4378,16 @@
},
{
"name": "symfony/error-handler",
- "version": "v5.4.42",
+ "version": "v5.4.46",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "db15ba0fd50890156ed40087ccedc7851a1f5b76"
+ "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363"
},
"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/d19ede7a2cafb386be9486c580649d0f9e3d0363",
+ "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363",
"shasum": ""
},
"require": {
@@ -4027,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/v5.4.42"
+ "source": "https://github.com/symfony/error-handler/tree/v5.4.46"
},
"funding": [
{
@@ -4043,7 +4445,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-23T12:34:05+00:00"
+ "time": "2024-11-05T14:17:06+00:00"
},
{
"name": "symfony/event-dispatcher",
@@ -4151,12 +4553,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "3.0-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -4209,16 +4611,16 @@
},
{
"name": "symfony/finder",
- "version": "v5.4.43",
+ "version": "v5.4.45",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "ae25a9145a900764158d439653d5630191155ca0"
+ "reference": "63741784cd7b9967975eec610b256eed3ede022b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/ae25a9145a900764158d439653d5630191155ca0",
- "reference": "ae25a9145a900764158d439653d5630191155ca0",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b",
+ "reference": "63741784cd7b9967975eec610b256eed3ede022b",
"shasum": ""
},
"require": {
@@ -4252,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/v5.4.43"
+ "source": "https://github.com/symfony/finder/tree/v5.4.45"
},
"funding": [
{
@@ -4268,20 +4670,20 @@
"type": "tidelift"
}
],
- "time": "2024-08-13T14:03:51+00:00"
+ "time": "2024-09-28T13:32:08+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v5.4.44",
+ "version": "v5.4.50",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "ae0d217e5932aa0b70ddb4cf7822cc76d48aee53"
+ "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609"
},
"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/1a0706e8b8041046052ea2695eb8aeee04f97609",
+ "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609",
"shasum": ""
},
"require": {
@@ -4328,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/v5.4.44"
+ "source": "https://github.com/symfony/http-foundation/tree/v5.4.50"
},
"funding": [
{
@@ -4339,25 +4741,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-15T07:55:06+00:00"
+ "time": "2025-11-03T12:58:48+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v5.4.44",
+ "version": "v5.4.51",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "788dcf72d9af7432a886aa3b0c5904d68087ba13"
+ "reference": "85432f7548b2757b8387f7e1a468abd62fc4c9bc"
},
"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/85432f7548b2757b8387f7e1a468abd62fc4c9bc",
+ "reference": "85432f7548b2757b8387f7e1a468abd62fc4c9bc",
"shasum": ""
},
"require": {
@@ -4441,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/v5.4.44"
+ "source": "https://github.com/symfony/http-kernel/tree/v5.4.51"
},
"funding": [
{
@@ -4452,25 +4858,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-21T05:47:58+00:00"
+ "time": "2026-01-28T07:10:35+00:00"
},
{
"name": "symfony/mime",
- "version": "v5.4.43",
+ "version": "v5.4.45",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "a02711d6ce461edada8c0f8641aa536709b99b47"
+ "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/a02711d6ce461edada8c0f8641aa536709b99b47",
- "reference": "a02711d6ce461edada8c0f8641aa536709b99b47",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064",
+ "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064",
"shasum": ""
},
"require": {
@@ -4526,7 +4936,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v5.4.43"
+ "source": "https://github.com/symfony/mime/tree/v5.4.45"
},
"funding": [
{
@@ -4542,11 +4952,11 @@
"type": "tidelift"
}
],
- "time": "2024-08-13T10:38:38+00:00"
+ "time": "2024-10-23T20:18:32+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -4570,8 +4980,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -4605,7 +5015,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
},
"funding": [
{
@@ -4616,6 +5026,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"
@@ -4625,16 +5039,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.31.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": {
@@ -4646,8 +5060,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -4683,7 +5097,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.33.0"
},
"funding": [
{
@@ -4694,25 +5108,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-09T11:45:10+00:00"
+ "time": "2025-06-27T09:58:17+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
- "version": "v1.31.0",
+ "version": "v1.33.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": {
@@ -4725,8 +5143,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -4766,7 +5184,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.33.0"
},
"funding": [
{
@@ -4777,16 +5195,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": "2024-09-10T14:38:51+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@@ -4807,8 +5229,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -4847,7 +5269,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.33.0"
},
"funding": [
{
@@ -4858,6 +5280,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"
@@ -4867,19 +5293,20 @@
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.31.0",
+ "version": "v1.33.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": {
@@ -4891,8 +5318,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -4927,7 +5354,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
},
"funding": [
{
@@ -4938,16 +5365,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": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/polyfill-php73",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
@@ -4965,8 +5396,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -5003,7 +5434,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0"
},
"funding": [
{
@@ -5014,6 +5445,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"
@@ -5023,16 +5458,16 @@
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.31.0",
+ "version": "v1.33.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": {
@@ -5041,8 +5476,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -5083,7 +5518,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
},
"funding": [
{
@@ -5094,16 +5529,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-01-02T08:10:11+00:00"
},
{
"name": "symfony/polyfill-php81",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
@@ -5121,8 +5560,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -5159,7 +5598,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0"
},
"funding": [
{
@@ -5170,6 +5609,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"
@@ -5179,16 +5622,16 @@
},
{
"name": "symfony/process",
- "version": "v5.4.44",
+ "version": "v5.4.51",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096"
+ "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/1b9fa82b5c62cd49da8c9e3952dd8531ada65096",
- "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096",
+ "url": "https://api.github.com/repos/symfony/process/zipball/467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f",
+ "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f",
"shasum": ""
},
"require": {
@@ -5221,7 +5664,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/v5.4.51"
},
"funding": [
{
@@ -5232,25 +5675,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-17T12:46:43+00:00"
+ "time": "2026-01-26T15:53:37+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v2.5.3",
+ "version": "v2.5.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3"
+ "reference": "f37b419f7aea2e9abf10abd261832cace12e3300"
},
"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/f37b419f7aea2e9abf10abd261832cace12e3300",
+ "reference": "f37b419f7aea2e9abf10abd261832cace12e3300",
"shasum": ""
},
"require": {
@@ -5266,12 +5713,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "2.5-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -5304,7 +5751,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v2.5.3"
+ "source": "https://github.com/symfony/service-contracts/tree/v2.5.4"
},
"funding": [
{
@@ -5320,7 +5767,7 @@
"type": "tidelift"
}
],
- "time": "2023-04-21T15:04:16+00:00"
+ "time": "2024-09-25T14:11:13+00:00"
},
{
"name": "symfony/string",
@@ -5524,12 +5971,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "3.0-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -5582,16 +6029,16 @@
},
{
"name": "symfony/var-dumper",
- "version": "v5.4.43",
+ "version": "v5.4.48",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "6be6a6a8af4818564e3726fc65cf936f34743cef"
+ "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8"
},
"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/42f18f170aa86d612c3559cfb3bd11a375df32c8",
+ "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8",
"shasum": ""
},
"require": {
@@ -5651,7 +6098,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v5.4.43"
+ "source": "https://github.com/symfony/var-dumper/tree/v5.4.48"
},
"funding": [
{
@@ -5667,30 +6114,30 @@
"type": "tidelift"
}
],
- "time": "2024-08-30T16:01:46+00:00"
+ "time": "2024-11-08T15:21:10+00:00"
},
{
"name": "vlucas/phpdotenv",
- "version": "v5.6.1",
+ "version": "v5.6.3",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
- "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2"
+ "reference": "955e7815d677a3eaa7075231212f2110983adecc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2",
- "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2",
+ "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",
@@ -5739,7 +6186,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.3"
},
"funding": [
{
@@ -5751,7 +6198,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:52:34+00:00"
+ "time": "2025-12-27T19:49:13+00:00"
},
{
"name": "voku/portable-ascii",
@@ -5827,76 +6274,18 @@
],
"time": "2022-01-24T18:55:24+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.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,46 +6340,43 @@
"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",
+ "version": "v0.7.2",
"source": {
"type": "git",
- "url": "https://github.com/PHPCSStandards/composer-installer.git",
- "reference": "4be43904336affa5c2f70744a348312336afd0da"
+ "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
+ "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da",
- "reference": "4be43904336affa5c2f70744a348312336afd0da",
+ "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
+ "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.4",
+ "php": ">=5.3",
"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"
+ "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/",
@@ -6006,7 +6392,7 @@
},
{
"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",
@@ -6030,10 +6416,10 @@
"tests"
],
"support": {
- "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
- "source": "https://github.com/PHPCSStandards/composer-installer"
+ "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
+ "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
- "time": "2023-01-05T11:28:13+00:00"
+ "time": "2022-02-04T12:51:07+00:00"
},
{
"name": "doctrine/instantiator",
@@ -6107,20 +6493,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": "*",
@@ -6128,8 +6514,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": {
@@ -6152,9 +6538,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",
@@ -6241,16 +6627,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.12.0",
+ "version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
- "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
@@ -6289,7 +6675,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.4"
},
"funding": [
{
@@ -6297,20 +6683,20 @@
"type": "tidelift"
}
],
- "time": "2024-06-12T14:39:25+00:00"
+ "time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.3.1",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"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/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -6329,7 +6715,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-master": "5.x-dev"
}
},
"autoload": {
@@ -6353,9 +6739,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.7.0"
},
- "time": "2024-10-08T18:51:32+00:00"
+ "time": "2025-12-06T11:56:16+00:00"
},
{
"name": "phar-io/manifest",
@@ -6477,30 +6863,30 @@
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.33.0",
+ "version": "2.3.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140"
+ "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140",
- "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a",
+ "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
"doctrine/annotations": "^2.0",
- "nikic/php-parser": "^4.15",
+ "nikic/php-parser": "^5.3.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^1.5",
- "phpstan/phpstan-phpunit": "^1.1",
- "phpstan/phpstan-strict-rules": "^1.0",
- "phpunit/phpunit": "^9.5",
+ "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",
@@ -6518,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/1.33.0"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2"
},
- "time": "2024-10-13T11:25:22+00:00"
+ "time": "2026-01-25T14:56:51+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -7159,16 +7545,16 @@
},
{
"name": "sebastian/comparator",
- "version": "4.0.8",
+ "version": "4.0.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
+ "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d",
+ "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d",
"shasum": ""
},
"require": {
@@ -7221,15 +7607,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.10"
},
"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": "2026-01-24T09:22:56+00:00"
},
{
"name": "sebastian/complexity",
@@ -7419,16 +7817,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": {
@@ -7484,28 +7882,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": {
@@ -7548,15 +7958,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",
@@ -7729,16 +8151,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": {
@@ -7780,15 +8202,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",
@@ -7955,32 +8389,32 @@
},
{
"name": "slevomat/coding-standard",
- "version": "8.15.0",
+ "version": "8.27.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "7d1d957421618a3803b593ec31ace470177d7817"
+ "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817",
- "reference": "7d1d957421618a3803b593ec31ace470177d7817",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/29bdaee8b65e7ed2b8e702b01852edba8bae1769",
+ "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769",
"shasum": ""
},
"require": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
- "php": "^7.2 || ^8.0",
- "phpstan/phpdoc-parser": "^1.23.1",
- "squizlabs/php_codesniffer": "^3.9.0"
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.0",
+ "php": "^7.4 || ^8.0",
+ "phpstan/phpdoc-parser": "^2.3.1",
+ "squizlabs/php_codesniffer": "^4.0.1"
},
"require-dev": {
- "phing/phing": "2.17.4",
- "php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.10.60",
- "phpstan/phpstan-deprecation-rules": "1.1.4",
- "phpstan/phpstan-phpunit": "1.3.16",
- "phpstan/phpstan-strict-rules": "1.5.2",
- "phpunit/phpunit": "8.5.21|9.6.8|10.5.11"
+ "phing/phing": "3.0.1|3.1.1",
+ "php-parallel-lint/php-parallel-lint": "1.4.0",
+ "phpstan/phpstan": "2.1.37",
+ "phpstan/phpstan-deprecation-rules": "2.0.3",
+ "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.49|12.5.7"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -8004,7 +8438,7 @@
],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/8.15.0"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.27.1"
},
"funding": [
{
@@ -8016,41 +8450,36 @@
"type": "tidelift"
}
],
- "time": "2024-03-09T15:20:58+00:00"
+ "time": "2026-01-25T15:57:07+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.10.3",
+ "version": "4.0.1",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "62d32998e820bddc40f99f8251958aed187a5c9c"
+ "reference": "0525c73950de35ded110cffafb9892946d7771b5"
},
"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/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"
@@ -8069,7 +8498,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",
@@ -8094,22 +8523,26 @@
{
"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-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": {
@@ -8138,7 +8571,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": [
{
@@ -8146,7 +8579,7 @@
"type": "github"
}
],
- "time": "2024-03-03T12:36:25+00:00"
+ "time": "2025-11-17T20:03:58+00:00"
}
],
"aliases": [],
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/public/gg/file.txt b/public/gg/file.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/Libraries/FirebaseClient.php b/src/Libraries/FirebaseClient.php
new file mode 100644
index 0000000..aaee89c
--- /dev/null
+++ b/src/Libraries/FirebaseClient.php
@@ -0,0 +1,393 @@
+
+ * @license https://mit-license.org/ MIT License
+ * @version GIT: 0.3.8
+ * @link https://github.com/spotlibs
+ */
+
+declare(strict_types=1);
+
+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 with file-based token persistence
+ *
+ * @category HttpClient
+ * @package Client
+ * @author Mufthi Ryanda
+ * @license https://mit-license.org/ MIT License
+ * @link https://github.com/spotlibs
+ */
+class FirebaseClient
+{
+ private GuzzleClient $httpClient;
+ private array $serviceAccount;
+ private string $proxyUrl = '';
+ private string $tokenFile;
+
+ /**
+ * Create Firebase client
+ *
+ * @param array $config Guzzle config options
+ *
+ * @throws RuntimeException When FIREBASE_CREDENTIALS env not set
+ */
+ 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($fullPath),
+ true,
+ 512,
+ 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,
+ ];
+
+ $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;
+ }
+
+ /**
+ * 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
+ *
+ * @return array Array with 'token' and 'expiry' keys
+ *
+ * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error
+ */
+ private function generateToken(): array
+ {
+ $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
+ );
+
+ $token = $responseBody['access_token'];
+ $expiresIn = $responseBody['expires_in'] ?? 3600;
+ $expiry = time() + $expiresIn;
+
+ Log::runtime()->info(
+ [
+ 'operation' => 'firebase_oauth',
+ 'url' => 'https://oauth2.googleapis.com/token',
+ 'responseTime' => round($elapsed * 1000),
+ 'httpCode' => $response->getStatusCode()
+ ]
+ );
+
+ return ['token' => $token, 'expiry' => $expiry];
+ }
+
+ /**
+ * Send FCM message
+ *
+ * @param array $message FCM message payload
+ *
+ * @return ResponseInterface
+ *
+ * @throws \GuzzleHttp\Exception\GuzzleException On HTTP error
+ */
+ public function sendMessage(array $message): ResponseInterface
+ {
+ $token = $this->getAccessToken();
+
+ $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;
+ }
+
+ 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'
+ ]
+ );
+
+ $newToken = $this->getAccessToken(true);
+
+ $retryRequest = new Request(
+ 'POST',
+ $url,
+ [
+ 'Authorization' => 'Bearer ' . $newToken,
+ 'Content-Type' => 'application/json'
+ ],
+ json_encode(['message' => $message], JSON_THROW_ON_ERROR)
+ );
+
+ return $this->httpClient->send($retryRequest, $options);
+ }
+
+ throw $e;
+ }
+ }
+
+ /**
+ * 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);
+
+ return str_replace(['+', '/', '='], ['-', '_', ''], $header . '.' . $payload . '.' . $signature);
+ }
+}
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/Libraries/Storage.php b/src/Libraries/Storage.php
new file mode 100644
index 0000000..58badad
--- /dev/null
+++ b/src/Libraries/Storage.php
@@ -0,0 +1,42 @@
+
+ * @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;
+
+/**
+ * Storage
+ *
+ * @category Library
+ * @package Libraries
+ * @author Made Mas Adi Winata
+ * @license https://mit-license.org/ MIT License
+ * @link https://github.com/spotlibs
+ */
+class Storage
+{
+ protected string $driver;
+
+ /**
+ * Parse file name from filepath
+ *
+ * @param string $filepath path of the file
+ *
+ * @return string
+ */
+ protected function getFileName(string $filepath): string
+ {
+ return basename($filepath);
+ }
+}
diff --git a/src/Libraries/StorageDrivers/Minio.php b/src/Libraries/StorageDrivers/Minio.php
new file mode 100644
index 0000000..e79320e
--- /dev/null
+++ b/src/Libraries/StorageDrivers/Minio.php
@@ -0,0 +1,165 @@
+
+ * @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\UploadedFile;
+use Illuminate\Support\Facades\Storage as FacadeStorage;
+use Illuminate\Support\Str;
+use Spotlibs\PhpLib\Exceptions\RuntimeException;
+use Spotlibs\PhpLib\Libraries\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 extends Storage implements StorageInterface
+{
+ /**
+ * Create a new NFS instance.
+ *
+ * @return void
+ */
+ 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
+ {
+ $this->driver = $driver;
+ return $this;
+ }
+ /**
+ * Upload file to disk
+ *
+ * @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, string $filename = ""): bool
+ {
+ $fileName = $filename == "" ? $file->getClientOriginalName() : $filename;
+ FacadeStorage::disk($this->driver)->put($dirpath . "/" . $fileName, $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
+ {
+ FacadeStorage::disk($this->driver)->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
+ {
+ FacadeStorage::disk($this->driver)->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
+ {
+ FacadeStorage::disk($this->driver)->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 securelink(string $filepath): string
+ {
+ /**
+ * Illuminate\Filesystem\FilesystemAdapter $disk file storage disk
+ *
+ * @var \Spotlibs\PhpLib\Libraries\StorageDrivers\MinioAdapter $disk file storage disk
+ */
+ $disk = FacadeStorage::disk($this->driver)->getDriver();
+ $urlpath = $disk->temporaryUrl($filepath, Carbon::now()->addSeconds((int) env('MINIO_EXPIRED_URL', 60)));
+ return $urlpath;
+ }
+ /**
+ * Create temporary URL for a folder in disk
+ *
+ * @param string $dirpath directory path to create secure link
+ *
+ * @return array
+ */
+ public function securelinkFolder(string $dirpath): array
+ {
+ $random = Str::random(40);
+ $linkFolder = "/var/www/html/public/securelink/$random";
+ 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);
+ $writeStream = fopen($linkFolder . "/" . $filename, 'w');
+ stream_copy_to_stream($fileStream, $writeStream);
+ fclose($fileStream);
+ fclose($writeStream);
+ $result[] = env('APP_URL') . "/securelink/" . $random . "/" . $filename;
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Libraries/StorageDrivers/MinioAdapter.php b/src/Libraries/StorageDrivers/MinioAdapter.php
new file mode 100644
index 0000000..9e81450
--- /dev/null
+++ b/src/Libraries/StorageDrivers/MinioAdapter.php
@@ -0,0 +1,138 @@
+
+ * @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 Carbon\Carbon;
+use League\Flysystem\AwsS3v3\AwsS3Adapter;
+use League\Flysystem\Filesystem;
+
+/**
+ * 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 Filesystem
+{
+ protected S3Client $publicClient;
+ protected string $bucket;
+
+ /**
+ * Create a new Minio Filesystem Adapter instance.
+ *
+ * @param AwsS3Adapter $adapter filesystem adapter
+ * @param array $config driver config
+ * @param S3Client $publicClient client for generating presigned URL
+ *
+ * @return void
+ */
+ public function __construct(AwsS3Adapter $adapter, array $config, S3Client $publicClient)
+ {
+ parent::__construct($adapter, $config);
+
+ $this->bucket = $config['bucket'];
+
+ // 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 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, int|string|Carbon $expiration, array $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();
+ }
+
+ /**
+ * 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 move(string $path, string $newpath): bool
+ {
+ try {
+ // Copy the file
+ if ($this->copy($path, $newpath)) {
+ // Delete the original
+ return $this->delete($path);
+ }
+
+ return false;
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get all files in a directory
+ *
+ * @param string $dirpath path of the directory
+ *
+ * @return bool
+ */
+ public function allFiles(string $dirpath): array
+ {
+ try {
+ $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
new file mode 100644
index 0000000..b19110c
--- /dev/null
+++ b/src/Libraries/StorageDrivers/NFS.php
@@ -0,0 +1,207 @@
+
+ * @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\UploadedFile;
+use Illuminate\Support\Str;
+use Spotlibs\PhpLib\Exceptions\RuntimeException;
+use Spotlibs\PhpLib\Libraries\Storage;
+
+/**
+ * Storage
+ *
+ * @category Library
+ * @package Libraries
+ * @author Made Mas Adi Winata
+ * @license https://mit-license.org/ MIT License
+ * @link https://github.com/spotlibs
+ */
+class NFS extends Storage implements StorageInterface
+{
+ /**
+ * Upload file to disk
+ *
+ * @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, string $filename = ''): bool
+ {
+ if (!is_dir($dirpath)) {
+ if (!mkdir($dirpath, 0755, true)) {
+ throw new RuntimeException("Failed to create destination directory: $dirpath");
+ }
+ }
+ $file->move($dirpath, $filename == '' ? $file->getClientOriginalName() : $filename);
+ 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));
+ try {
+ $this->createDirectory($destDir);
+ exec("cp $srcPath $destPath");
+ } catch (\Throwable $th) {
+ throw new RuntimeException("Failed to copy from $srcPath to $destPath. " . $th->getMessage());
+ }
+ 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
+ {
+ 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, include filename if you want to change its name
+ *
+ * @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));
+ try {
+ $this->createDirectory($destDir);
+ exec("mv $srcPath $destPath");
+ } catch (\Throwable $th) {
+ throw new RuntimeException("Failed to move from $srcPath to $destPath. " . $th->getMessage());
+ }
+ return true;
+ }
+ /**
+ * Create temporary URL for file in disk
+ *
+ * @param string $filepath file path to create secure link
+ *
+ * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException
+ *
+ * @return string
+ */
+ 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);
+ $random = $extension !== "" ? "$random.$extension" : $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";
+ }
+ /**
+ * Create temporary URL for a folder in disk
+ *
+ * @param string $dirpath directory path to create secure link
+ *
+ * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException
+ *
+ * @return array
+ */
+ public function securelinkFolder(string $dirpath): array
+ {
+ if (!is_dir($dirpath)) {
+ throw new RuntimeException("Directory not found within dirpath: $dirpath");
+ }
+ $random = Str::random(40);
+ 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/public", env('APP_URL'), $r);
+ }
+ 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());
+ }
+ }
+
+ /**
+ * Extract file's extension
+ *
+ * @param string $filepath path of the file
+ *
+ * @return string
+ */
+ private function getExtension(string $filepath): string
+ {
+ $temp = explode(".", basename($filepath));
+ if (\count($temp) > 0) {
+ return $temp[1];
+ }
+ return "";
+ }
+}
diff --git a/src/Libraries/StorageDrivers/StorageInterface.php b/src/Libraries/StorageDrivers/StorageInterface.php
new file mode 100644
index 0000000..a33a390
--- /dev/null
+++ b/src/Libraries/StorageDrivers/StorageInterface.php
@@ -0,0 +1,95 @@
+
+ * @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\UploadedFile;
+
+/**
+ * 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 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, string $filename = ''): 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
+ *
+ * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException
+ *
+ * @return void
+ */
+ public function securelink(string $filepath): string;
+ /**
+ * Create temporary URL for a folder in disk
+ *
+ * @param string $dirpath directory path to create secure link
+ *
+ * @throws \Spotlibs\PhpLib\Exceptions\RuntimeException
+ *
+ * @return array
+ */
+ public function securelinkFolder(string $dirpath): array;
+}
diff --git a/src/Providers/MinioStorageServiceProvider.php b/src/Providers/MinioStorageServiceProvider.php
new file mode 100644
index 0000000..ecca2e6
--- /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 Spotlibs\PhpLib\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()
+ {
+
+ }
+}
diff --git a/tests/Libraries/FirebaseClientTest.php b/tests/Libraries/FirebaseClientTest.php
new file mode 100644
index 0000000..32927c2
--- /dev/null
+++ b/tests/Libraries/FirebaseClientTest.php
@@ -0,0 +1,291 @@
+
+ * @license https://mit-license.org/ MIT License
+ * @version GIT: 0.3.8
+ * @link https://github.com/spotlibs
+ */
+
+declare(strict_types=1);
+
+namespace Tests\Libraries;
+
+use GuzzleHttp\Client as GuzzleClient;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7\Request;
+use Mockery;
+use Spotlibs\PhpLib\Libraries\FirebaseClient;
+use Tests\TestCase;
+
+// Test helper class that extends FirebaseClient
+class TestableFirebaseClient extends FirebaseClient
+{
+ 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' => 'fake-key',
+ 'client_email' => 'test@test-project.iam.gserviceaccount.com',
+ 'client_id' => '12345',
+ ];
+
+ /** @test */
+ public function testSendMessage(): void
+ {
+ $mockResponse = new Response(
+ 200,
+ [],
+ json_encode(['name' => 'projects/test-project/messages/123'])
+ );
+
+ $guzzleMock = Mockery::mock(GuzzleClient::class);
+ $guzzleMock->shouldReceive('send')
+ ->once()
+ ->andReturn($mockResponse);
+
+ $client = $this->createMockedClient($guzzleMock);
+
+ $message = [
+ 'token' => 'device_token_123',
+ 'notification' => [
+ 'title' => 'Test',
+ 'body' => 'Test message'
+ ]
+ ];
+
+ $response = $client->sendMessage($message);
+
+ $this->assertEquals(200, $response->getStatusCode());
+ }
+
+ /** @test */
+ public function testSendMessageRetryOn401(): void
+ {
+ $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 */
+ public function testSendMulticast(): void
+ {
+ $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']);
+ }
+
+ /** @test */
+ public function testSendMulticastWithFailures(): void
+ {
+ $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']);
+ }
+
+ /** @test */
+ 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);
+
+ $tokens = ['token1', 'token2'];
+ $result = $client->sendMulticast($tokens);
+
+ $this->assertEquals(1, $result['success']);
+ $this->assertEquals(1, $result['failure']);
+ $this->assertStringContainsString('Network error', $result['responses'][1]['error']);
+ }
+
+ /** @test */
+ public function testSendMulticastWithData(): void
+ {
+ $mockResponse = new Response(200, [], json_encode(['name' => 'projects/test-project/messages/123']));
+
+ $guzzleMock = Mockery::mock(GuzzleClient::class);
+ $guzzleMock->shouldReceive('send')
+ ->once()
+ ->andReturn($mockResponse);
+
+ $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']);
+ }
+
+ /** @test */
+ public function testSetProxy(): void
+ {
+ $guzzleMock = Mockery::mock(GuzzleClient::class);
+ $client = $this->createMockedClient($guzzleMock);
+
+ $result = $client->setProxy('http://proxy.example.com:8080');
+
+ $this->assertInstanceOf(TestableFirebaseClient::class, $result);
+ }
+
+ private function createMockedClient($guzzleMock): TestableFirebaseClient
+ {
+ return new TestableFirebaseClient($guzzleMock, $this->mockServiceAccount);
+ }
+}
\ No newline at end of file