diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..22d9944 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,32 @@ +# Pull Request + +## Description +Please include a summary of the changes and the related issue. Please also include relevant motivation and context. + +Fixes # (issue) + +## Type of change +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. + +- [ ] Test A +- [ ] Test B + +**Test Configuration**: +* PHP version: +* Laravel version: + +## Checklist: +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml new file mode 100644 index 0000000..957c6d1 --- /dev/null +++ b/.github/workflows/code-analysis.yml @@ -0,0 +1,30 @@ +name: Coverage + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + coverage: + runs-on: ubuntu-latest + name: Coverage Report (PHP 8.3) + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + coverage: xdebug + + - name: Install dependencies + run: | + composer update --prefer-stable --prefer-dist --no-interaction + + - name: Execute tests with coverage + run: vendor/bin/phpunit --coverage-text --testdox diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..d27faa2 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,52 @@ +name: Tests + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + php: [8.2, 8.3] + laravel: [11.*, 12.*] + stability: [prefer-stable] + include: + - laravel: 11.* + testbench: ^9.0 + - laravel: 12.* + testbench: ^10.0 + + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + coverage: none + + - name: Setup problem matchers + run: | + echo "::add-matcher::${{ runner.tool_cache }}/php.json" + echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install dependencies + run: | + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update + composer update --${{ matrix.stability }} --prefer-dist --no-interaction + + - name: List Installed Dependencies + run: composer show -D + + - name: Execute tests + run: vendor/bin/phpunit --testdox diff --git a/.gitignore b/.gitignore index 48b8bf9..453812d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ vendor/ +.phpunit.cache/ +coverage/ +.DS_Store diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..b8dd30f --- /dev/null +++ b/TESTING.md @@ -0,0 +1,269 @@ +# SmartCache Testing Guide + +This guide explains how to run tests for the SmartCache Laravel package without needing a full Laravel installation. + +## Overview + +The test suite uses: +- **PHPUnit 10** - Testing framework +- **Orchestra Testbench** - Minimal Laravel environment for package testing +- **Mockery** - Mocking framework for isolated unit tests + +## Installation + +First, install the development dependencies: + +```bash +composer install +``` + +## Running Tests + +### Run All Tests +```bash +composer test +# or +vendor/bin/phpunit +``` + +### Run Specific Test Suites +```bash +# Unit tests only +vendor/bin/phpunit --testsuite=Unit + +# Feature tests only +vendor/bin/phpunit --testsuite=Feature + +# Specific test file +vendor/bin/phpunit tests/Unit/SmartCacheTest.php + +# Specific test method +vendor/bin/phpunit --filter test_can_store_and_retrieve_simple_value +``` + +### Generate Coverage Report +```bash +composer test-coverage +# Generates HTML coverage report in ./coverage/ directory +``` + +### Test with Different PHP Versions +If you have multiple PHP versions installed: +```bash +php8.1 vendor/bin/phpunit +php8.2 vendor/bin/phpunit +php8.3 vendor/bin/phpunit +``` + +## Test Structure + +``` +tests/ +├── bootstrap.php # Test bootstrap (sets up environment) +├── TestCase.php # Base test class +├── Unit/ # Unit tests (isolated component testing) +│ ├── SmartCacheTest.php # Main SmartCache functionality +│ ├── Console/ # Console command tests +│ │ ├── ClearCommandTest.php +│ │ └── StatusCommandTest.php +│ ├── Providers/ # Service provider tests +│ │ └── SmartCacheServiceProviderTest.php +│ └── Strategies/ # Strategy tests +│ ├── CompressionStrategyTest.php +│ └── ChunkingStrategyTest.php +├── Feature/ # Integration tests +│ └── SmartCacheIntegrationTest.php +└── Fixtures/ # Test fixtures and data +``` + +## Test Categories + +### Unit Tests +- Test individual components in isolation +- Use mocks to avoid external dependencies +- Fast execution +- Located in `tests/Unit/` + +### Feature Tests +- Test complete workflows and integration +- Use real Laravel components +- Test the package as end users would use it +- Located in `tests/Feature/` + +## Key Testing Features + +### 1. Orchestra Testbench Integration +The `TestCase` class extends Orchestra Testbench, providing: +- Minimal Laravel application environment +- Service container with Laravel services +- Configuration management +- Cache system simulation + +### 2. Smart Test Data Helpers +Built-in helper methods for creating test data: +```php +$this->createCompressibleData(); // Large repetitive string +$this->createChunkableData(); // Large array for chunking +$this->createLargeTestData(100); // Array with 100 complex items +``` + +### 3. Custom Assertions +Specialized assertions for testing optimizations: +```php +$this->assertValueIsOptimized($original, $cached); +$this->assertValueIsCompressed($value); +$this->assertValueIsChunked($value); +``` + +### 4. Configuration Testing +Tests cover various configuration scenarios: +- Strategies enabled/disabled +- Custom thresholds +- Different compression levels +- Custom chunk sizes + +### 5. Console Command Testing +Command tests verify: +- Correct output formatting +- Proper exit codes +- Integration with SmartCache service +- Error handling + +## Testing Without Laravel Installation + +The package tests run completely independently using Orchestra Testbench: + +1. **No Laravel Project Required** - Tests create a minimal Laravel environment +2. **Isolated Dependencies** - Only requires packages specified in `composer.json` +3. **Cross-Version Compatible** - Works with Laravel 8.0+ and PHP 8.1+ +4. **Fast Execution** - No database migrations or complex setup + +## Environment Configuration + +Test environment is configured in `TestCase::defineEnvironment()`: +- Cache driver: `array` (in-memory) +- Debug mode: enabled +- Optimized thresholds for testing (lower than production) + +## Continuous Integration + +The test suite is designed to work well in CI environments: + +```yaml +# Example GitHub Actions configuration +- name: Run Tests + run: | + composer install + vendor/bin/phpunit --coverage-clover=coverage.xml +``` + +## Debugging Tests + +### Enable Debug Output +```bash +vendor/bin/phpunit --debug +``` + +### Stop on First Failure +```bash +vendor/bin/phpunit --stop-on-failure +``` + +### Verbose Output +```bash +vendor/bin/phpunit --verbose +``` + +### Test Specific Cache Driver +The package can be tested against different cache drivers by modifying the test configuration. + +## Writing New Tests + +### Unit Test Example +```php +app->make(\SmartCache\Contracts\SmartCache::class); + + // Test your functionality + $smartCache->put('test-key', 'test-value'); + $this->assertEquals('test-value', $smartCache->get('test-key')); + } +} +``` + +### Feature Test Example +```php +app->make(SmartCache::class); + + // Test complete user workflow + $largeData = $this->createCompressibleData(); + $smartCache->put('integration-test', $largeData, 3600); + + $retrieved = $smartCache->get('integration-test'); + $this->assertEquals($largeData, $retrieved); + + // Verify optimization occurred + $managedKeys = $smartCache->getManagedKeys(); + $this->assertContains('integration-test', $managedKeys); + } +} +``` + +## Troubleshooting + +### Common Issues + +1. **Memory Limit Errors** + ```bash + php -dmemory_limit=1G vendor/bin/phpunit + ``` + +2. **Missing Extensions** + Ensure required PHP extensions are installed: + - `ext-zlib` (for compression) + - `ext-json` + - `ext-mbstring` + +3. **Composer Autoload Issues** + ```bash + composer dump-autoload + ``` + +4. **Cache Permission Issues** + The test bootstrap creates temporary cache directories automatically. + +### Getting Help + +- Check the test output for detailed error messages +- Use `--debug` flag for additional debugging information +- Review the test configuration in `phpunit.xml` +- Examine the base `TestCase` class for available helpers + +## Performance Considerations + +- Unit tests should complete in under 1 second each +- Feature tests may take longer due to data processing +- Use smaller test datasets when possible +- Clean up test data in tearDown methods + +This testing setup ensures your SmartCache package works correctly across different environments without requiring a full Laravel installation. diff --git a/composer.json b/composer.json index 64414ff..69d2445 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,13 @@ "illuminate/console": ">=8.0", "illuminate/contracts": ">=8.0" }, + "require-dev": { + "phpunit/phpunit": "^9.0|^10.0|^11.0", + "orchestra/testbench": "^10.0", + "mockery/mockery": "^1.5", + "symfony/var-dumper": "^6.0|^7.0", + "laravel/framework": "12.*" + }, "autoload": { "psr-4": { "SmartCache\\": "src/" @@ -47,6 +54,15 @@ "src/helpers.php" ] }, + "autoload-dev": { + "psr-4": { + "SmartCache\\Tests\\": "tests/" + } + }, + "scripts": { + "test": "vendor/bin/phpunit --testdox", + "test-coverage": "vendor/bin/phpunit --coverage-html coverage --testdox" + }, "extra": { "laravel": { "providers": [ @@ -59,4 +75,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index cb1076d..dc387c0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,68 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "676c4c19f7338b521b1a66d25dd10ed3", + "content-hash": "50d06c0d65e17e36fe6ea174d8d1dd9b", "packages": [ + { + "name": "brick/math", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.13.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-03-29T13:50:30+00:00" + }, { "name": "carbonphp/carbon-doctrine-types", "version": "3.2.0", @@ -75,35 +135,109 @@ ], "time": "2024-02-09T16:56:22+00:00" }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+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/", @@ -148,7 +282,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": [ { @@ -164,41 +298,36 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { - "name": "illuminate/bus", - "version": "v12.10.0", + "name": "doctrine/lexer", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/illuminate/bus.git", - "reference": "5bbb523f1317395ce9e9ded59d69d04a714b081d" + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/bus/zipball/5bbb523f1317395ce9e9ded59d69d04a714b081d", - "reference": "5bbb523f1317395ce9e9ded59d69d04a714b081d", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/pipeline": "^12.0", - "illuminate/support": "^12.0", - "php": "^8.2" + "php": "^8.1" }, - "suggest": { - "illuminate/queue": "Required to use closures when chaining jobs (^12.0)." + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "12.x-dev" - } - }, "autoload": { "psr-4": { - "Illuminate\\Bus\\": "" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -207,60 +336,82 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "The Illuminate Bus package.", - "homepage": "https://laravel.com", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, - "time": "2025-03-19T20:10:05+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" }, { - "name": "illuminate/cache", - "version": "v12.10.0", + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", "source": { "type": "git", - "url": "https://github.com/illuminate/cache.git", - "reference": "a90be9ccc7cb7eead065ab035a7c844428ca286a" + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/cache/zipball/a90be9ccc7cb7eead065ab035a7c844428ca286a", - "reference": "a90be9ccc7cb7eead065ab035a7c844428ca286a", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "php": "^8.2" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" }, - "provide": { - "psr/simple-cache-implementation": "1.0|2.0|3.0" + "replace": { + "mtdowling/cron-expression": "^1.0" }, - "suggest": { - "ext-apcu": "Required to use the APC cache driver.", - "ext-filter": "Required to use the DynamoDb cache driver.", - "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^12.0).", - "illuminate/filesystem": "Required to use the file cache driver (^12.0).", - "illuminate/redis": "Required to use the redis cache driver (^12.0).", - "symfony/cache": "Required to use PSR-6 cache bridge (^7.2)." + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Illuminate\\Cache\\": "" + "Cron\\": "src/Cron/" } }, "notification-url": "https://packagist.org/downloads/", @@ -269,55 +420,63 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" } ], - "description": "The Illuminate Cache package.", - "homepage": "https://laravel.com", + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, - "time": "2025-04-18T14:50:25+00:00" + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" }, { - "name": "illuminate/collections", - "version": "v12.10.0", + "name": "egulias/email-validator", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/illuminate/collections.git", - "reference": "7f8a89e1e484fea952cdd8400bab2e277fa4f903" + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/7f8a89e1e484fea952cdd8400bab2e277fa4f903", - "reference": "7f8a89e1e484fea952cdd8400bab2e277fa4f903", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { - "illuminate/conditionable": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "php": "^8.2" + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { - "illuminate/http": "Required to convert collections to API resources (^12.0).", - "symfony/var-dumper": "Required to use the dump method (^7.2)." + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { - "files": [ - "functions.php", - "helpers.php" - ], "psr-4": { - "Illuminate\\Support\\": "" + "Egulias\\EmailValidator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -326,44 +485,62 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Eduardo Gulias Davis" } ], - "description": "The Illuminate Collections package.", - "homepage": "https://laravel.com", + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" }, - "time": "2025-04-21T14:14:46+00:00" + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" }, { - "name": "illuminate/conditionable", - "version": "v12.10.0", + "name": "fruitcake/php-cors", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/illuminate/conditionable.git", - "reference": "babbddf119c7aabcce0e369f77e139bccbdec858" + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/conditionable/zipball/babbddf119c7aabcce0e369f77e139bccbdec858", - "reference": "babbddf119c7aabcce0e369f77e139bccbdec858", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", "shasum": "" }, "require": { - "php": "^8.2" + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "1.2-dev" } }, "autoload": { "psr-4": { - "Illuminate\\Support\\": "" + "Fruitcake\\Cors\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -372,64 +549,62 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" } ], - "description": "The Illuminate Conditionable package.", - "homepage": "https://laravel.com", + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" }, - "time": "2025-04-18T12:44:14+00:00" + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" }, { - "name": "illuminate/console", - "version": "v12.10.0", + "name": "graham-campbell/result-type", + "version": "v1.1.3", "source": { "type": "git", - "url": "https://github.com/illuminate/console.git", - "reference": "02aeaac8cc603935ddf63be288cb4fdcd5a99c56" + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/console/zipball/02aeaac8cc603935ddf63be288cb4fdcd5a99c56", - "reference": "02aeaac8cc603935ddf63be288cb4fdcd5a99c56", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { - "ext-mbstring": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "illuminate/view": "^12.0", - "laravel/prompts": "^0.3.0", - "nunomaduro/termwind": "^2.0", - "php": "^8.2", - "symfony/console": "^7.2.0", - "symfony/polyfill-php83": "^1.31", - "symfony/process": "^7.2.0" + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" }, - "suggest": { - "dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).", - "ext-pcntl": "Required to use signal trapping.", - "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^12.0).", - "illuminate/container": "Required to use the scheduler (^12.0).", - "illuminate/filesystem": "Required to use the generator command (^12.0).", - "illuminate/queue": "Required to use closures for scheduled jobs (^12.0)." + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "12.x-dev" - } - }, "autoload": { "psr-4": { - "Illuminate\\Console\\": "" + "GrahamCampbell\\ResultType\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -438,49 +613,86 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" } ], - "description": "The Illuminate Console package.", - "homepage": "https://laravel.com", + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, - "time": "2025-04-16T14:44:02+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" }, { - "name": "illuminate/container", - "version": "v12.10.0", + "name": "guzzlehttp/guzzle", + "version": "7.10.0", "source": { "type": "git", - "url": "https://github.com/illuminate/container.git", - "reference": "cdd99204b29acf795a02f778542df5a5244361fd" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/cdd99204b29acf795a02f778542df5a5244361fd", - "reference": "cdd99204b29acf795a02f778542df5a5244361fd", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { - "illuminate/contracts": "^12.0", - "php": "^8.2", - "psr/container": "^1.1.1|^2.0.1" + "ext-json": "*", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" }, "provide": { - "psr/container-implementation": "1.1|2.0" + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "12.x-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { - "Illuminate\\Container\\": "" + "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -489,46 +701,104 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], - "description": "The Illuminate Container package.", - "homepage": "https://laravel.com", + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, - "time": "2025-03-22T17:41:27+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-08-23T22:36:01+00:00" }, { - "name": "illuminate/contracts", - "version": "v12.10.0", + "name": "guzzlehttp/promises", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/illuminate/contracts.git", - "reference": "bbaec083da240396f2186f4c3a9952da207f28a0" + "url": "https://github.com/guzzle/promises.git", + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/bbaec083da240396f2186f4c3a9952da207f28a0", - "reference": "bbaec083da240396f2186f4c3a9952da207f28a0", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { - "php": "^8.2", - "psr/container": "^1.1.1|^2.0.1", - "psr/simple-cache": "^1.0|^2.0|^3.0" + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "12.x-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { - "Illuminate\\Contracts\\": "" + "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -537,53 +807,92 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], - "description": "The Illuminate Contracts package.", - "homepage": "https://laravel.com", + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, - "time": "2025-03-19T20:10:05+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:34:08+00:00" }, { - "name": "illuminate/events", - "version": "v12.10.0", + "name": "guzzlehttp/psr7", + "version": "2.8.0", "source": { "type": "git", - "url": "https://github.com/illuminate/events.git", - "reference": "80fc4cdfef9c33a59c998d2eb361eb6ae7c124bf" + "url": "https://github.com/guzzle/psr7.git", + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/80fc4cdfef9c33a59c998d2eb361eb6ae7c124bf", - "reference": "80fc4cdfef9c33a59c998d2eb361eb6ae7c124bf", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "php": "^8.2" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "12.x-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "functions.php" - ], "psr-4": { - "Illuminate\\Events\\": "" + "GuzzleHttp\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -592,52 +901,326 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], - "description": "The Illuminate Events package.", - "homepage": "https://laravel.com", + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, - "time": "2025-03-19T20:10:05+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-08-23T21:21:41+00:00" }, { - "name": "illuminate/filesystem", - "version": "v12.10.0", + "name": "guzzlehttp/uri-template", + "version": "v1.0.5", "source": { "type": "git", - "url": "https://github.com/illuminate/filesystem.git", - "reference": "4fa2995bad173c1a0067b285bb7fef47a4b441c6" + "url": "https://github.com/guzzle/uri-template.git", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/filesystem/zipball/4fa2995bad173c1a0067b285bb7fef47a4b441c6", - "reference": "4fa2995bad173c1a0067b285bb7fef47a4b441c6", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:27:06+00:00" + }, + { + "name": "laravel/framework", + "version": "v12.26.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "085a367a32ba86fcfa647bfc796098ae6f795b09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/085a367a32ba86fcfa647bfc796098ae6f795b09", + "reference": "085a367a32ba86fcfa647bfc796098ae6f795b09", + "shasum": "" + }, + "require": { + "brick/math": "^0.11|^0.12|^0.13", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", "php": "^8.2", - "symfony/finder": "^7.2.0" + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/polyfill-php85": "^1.33", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.6.3", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" }, "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", - "ext-hash": "Required to use the Filesystem class.", - "illuminate/http": "Required for handling uploaded files (^12.0).", - "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", - "symfony/mime": "Required to enable support for guessing extensions (^7.2)." + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." }, "type": "library", "extra": { @@ -647,10 +1230,22 @@ }, "autoload": { "files": [ - "functions.php" + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" ], "psr-4": { - "Illuminate\\Filesystem\\": "" + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -663,88 +1258,110 @@ "email": "taylor@laravel.com" } ], - "description": "The Illuminate Filesystem package.", + "description": "The Laravel Framework.", "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-19T20:10:05+00:00" + "time": "2025-08-29T14:15:53+00:00" }, { - "name": "illuminate/macroable", - "version": "v12.10.0", + "name": "laravel/prompts", + "version": "v0.3.6", "source": { "type": "git", - "url": "https://github.com/illuminate/macroable.git", - "reference": "e862e5648ee34004fa56046b746f490dfa86c613" + "url": "https://github.com/laravel/prompts.git", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/macroable/zipball/e862e5648ee34004fa56046b746f490dfa86c613", - "reference": "e862e5648ee34004fa56046b746f490dfa86c613", + "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077", "shasum": "" }, "require": { - "php": "^8.2" + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-main": "0.3.x-dev" } }, "autoload": { + "files": [ + "src/helpers.php" + ], "psr-4": { - "Illuminate\\Support\\": "" + "Laravel\\Prompts\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "The Illuminate Macroable package.", - "homepage": "https://laravel.com", + "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.6" }, - "time": "2024-07-23T16:31:01+00:00" + "time": "2025-07-07T14:17:42+00:00" }, { - "name": "illuminate/pipeline", - "version": "v12.10.0", + "name": "laravel/serializable-closure", + "version": "v2.0.4", "source": { "type": "git", - "url": "https://github.com/illuminate/pipeline.git", - "reference": "3c6df979e7e8ef09183a610cc0383179c1aba309" + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/pipeline/zipball/3c6df979e7e8ef09183a610cc0383179c1aba309", - "reference": "3c6df979e7e8ef09183a610cc0383179c1aba309", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", "shasum": "" }, "require": { - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0", - "php": "^8.2" + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "Illuminate\\Pipeline\\": "" + "Laravel\\SerializableClosure\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -755,267 +1372,320 @@ { "name": "Taylor Otwell", "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" } ], - "description": "The Illuminate Pipeline package.", - "homepage": "https://laravel.com", + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-03-19T20:10:05+00:00" + "time": "2025-03-19T13:51:03+00:00" }, { - "name": "illuminate/support", - "version": "v12.10.0", + "name": "league/commonmark", + "version": "2.7.1", "source": { "type": "git", - "url": "https://github.com/illuminate/support.git", - "reference": "80b1b5bdf67f9ebd41fc52b15b2aa4d0ea41cd72" + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/80b1b5bdf67f9ebd41fc52b15b2aa4d0ea41cd72", - "reference": "80b1b5bdf67f9ebd41fc52b15b2aa4d0ea41cd72", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", "shasum": "" }, "require": { - "doctrine/inflector": "^2.0", - "ext-ctype": "*", - "ext-filter": "*", "ext-mbstring": "*", - "illuminate/collections": "^12.0", - "illuminate/conditionable": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "nesbot/carbon": "^3.8.4", - "php": "^8.2", - "voku/portable-ascii": "^2.0.2" - }, - "conflict": { - "tightenco/collect": "<5.5.33" + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" }, - "replace": { - "spatie/once": "*" + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, "suggest": { - "illuminate/filesystem": "Required to use the Composer class (^12.0).", - "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", - "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.6).", - "league/uri": "Required to use the Uri class (^7.5.1).", - "ramsey/uuid": "Required to use Str::uuid() (^4.7).", - "symfony/process": "Required to use the Composer class (^7.2).", - "symfony/uid": "Required to use Str::ulid() (^7.2).", - "symfony/var-dumper": "Required to use the dd function (^7.2).", - "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)." + "symfony/yaml": "v2.3+ required if using the Front Matter extension" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-main": "2.8-dev" } }, "autoload": { - "files": [ - "functions.php", - "helpers.php" - ], "psr-4": { - "Illuminate\\Support\\": "" + "League\\CommonMark\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], - "description": "The Illuminate Support package.", - "homepage": "https://laravel.com", + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" }, - "time": "2025-04-18T12:52:24+00:00" + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-07-20T12:47:49+00:00" }, { - "name": "illuminate/view", - "version": "v12.10.0", + "name": "league/config", + "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/illuminate/view.git", - "reference": "3b80cfb52b07132ef285fa2939dd6acd40a3f82e" + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/view/zipball/3b80cfb52b07132ef285fa2939dd6acd40a3f82e", - "reference": "3b80cfb52b07132ef285fa2939dd6acd40a3f82e", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/events": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "php": "^8.2" + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-main": "1.2-dev" } }, "autoload": { "psr-4": { - "Illuminate\\View\\": "" + "League\\Config\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], - "description": "The Illuminate View package.", - "homepage": "https://laravel.com", + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" }, - "time": "2025-04-21T14:13:20+00:00" + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" }, { - "name": "laravel/prompts", - "version": "v0.3.5", + "name": "league/flysystem", + "version": "3.30.0", "source": { "type": "git", - "url": "https://github.com/laravel/prompts.git", - "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", - "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", "shasum": "" }, "require": { - "composer-runtime-api": "^2.2", - "ext-mbstring": "*", - "php": "^8.1", - "symfony/console": "^6.2|^7.0" + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" }, "conflict": { - "illuminate/console": ">=10.17.0 <10.25.0", - "laravel/framework": ">=10.17.0 <10.25.0" + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" }, "require-dev": { - "illuminate/collections": "^10.0|^11.0|^12.0", - "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" - }, - "suggest": { - "ext-pcntl": "Required for the spinner to be animated." + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "0.3.x-dev" - } - }, "autoload": { - "files": [ - "src/helpers.php" - ], "psr-4": { - "Laravel\\Prompts\\": "src/" + "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Add beautiful and user-friendly forms to your command-line applications.", + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], "support": { - "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.5" + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" }, - "time": "2025-02-11T13:34:40+00:00" + "time": "2025-06-25T13:29:59+00:00" }, { - "name": "nesbot/carbon", - "version": "3.9.0", + "name": "league/flysystem-local", + "version": "3.30.0", "source": { "type": "git", - "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d" + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d", - "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "<100.0", - "ext-json": "*", - "php": "^8.1", - "psr/clock": "^1.0", - "symfony/clock": "^6.3 || ^7.0", - "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "doctrine/dbal": "^3.6.3 || ^4.0", - "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.57.2", - "kylekatarnls/multi-tester": "^2.5.3", - "ondrejmirtes/better-reflection": "^6.25.0.4", - "phpmd/phpmd": "^2.15.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.11.2", - "phpunit/phpunit": "^10.5.20", - "squizlabs/php_codesniffer": "^3.9.0" + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" }, - "bin": [ - "bin/carbon" - ], "type": "library", - "extra": { - "laravel": { - "providers": [ - "Carbon\\Laravel\\ServiceProvider" - ] - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - }, - "branch-alias": { - "dev-2.x": "2.x-dev", - "dev-master": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Carbon\\": "src/Carbon/" + "League\\Flysystem\\Local\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1024,89 +1694,50 @@ ], "authors": [ { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "https://markido.com" - }, - { - "name": "kylekatarnls", - "homepage": "https://github.com/kylekatarnls" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "https://carbon.nesbot.com", + "description": "Local filesystem adapter for Flysystem.", "keywords": [ - "date", - "datetime", - "time" + "Flysystem", + "file", + "files", + "filesystem", + "local" ], "support": { - "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/CarbonPHP/carbon/issues", - "source": "https://github.com/CarbonPHP/carbon" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" }, - "funding": [ - { - "url": "https://github.com/sponsors/kylekatarnls", - "type": "github" - }, - { - "url": "https://opencollective.com/Carbon#sponsor", - "type": "opencollective" - }, - { - "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", - "type": "tidelift" - } - ], - "time": "2025-03-27T12:57:33+00:00" + "time": "2025-05-21T10:34:19+00:00" }, { - "name": "nunomaduro/termwind", - "version": "v2.3.0", + "name": "league/mime-type-detection", + "version": "1.16.0", "source": { "type": "git", - "url": "https://github.com/nunomaduro/termwind.git", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": "^8.2", - "symfony/console": "^7.1.8" + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "illuminate/console": "^11.33.2", - "laravel/pint": "^1.18.2", - "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.11", - "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.8", - "thecodingmachine/phpstan-strict-rules": "^1.0.0" + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" }, "type": "library", - "extra": { - "laravel": { - "providers": [ - "Termwind\\Laravel\\TermwindServiceProvider" - ] - }, - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, "autoload": { - "files": [ - "src/Functions.php" - ], "psr-4": { - "Termwind\\": "src/" + "League\\MimeTypeDetection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1115,60 +1746,67 @@ ], "authors": [ { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "Its like Tailwind CSS, but for the console.", - "keywords": [ - "cli", - "console", - "css", - "package", - "php", - "style" - ], + "description": "Mime-type detection for Flysystem", "support": { - "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" }, "funding": [ { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", + "url": "https://github.com/frankdejonge", "type": "github" }, { - "url": "https://github.com/xiCO2k", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" } ], - "time": "2024-11-21T10:39:51+00:00" + "time": "2024-09-21T08:32:55+00:00" }, { - "name": "psr/clock", - "version": "1.0.0", + "name": "league/uri", + "version": "7.5.1", "source": { "type": "git", - "url": "https://github.com/php-fig/clock.git", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0" + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, "autoload": { "psr-4": { - "Psr\\Clock\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1177,51 +1815,84 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" } ], - "description": "Common interface for reading the clock.", - "homepage": "https://github.com/php-fig/clock", + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" ], "support": { - "issues": "https://github.com/php-fig/clock/issues", - "source": "https://github.com/php-fig/clock/tree/1.0.0" + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" }, - "time": "2022-11-25T14:36:26+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" }, { - "name": "psr/container", - "version": "2.0.2", + "name": "league/uri-interfaces", + "version": "7.5.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", "shasum": "" }, "require": { - "php": ">=7.4.0" + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "7.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1230,51 +1901,113 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" }, - "time": "2021-11-05T16:47:00+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" }, { - "name": "psr/simple-cache", - "version": "3.0.0", + "name": "monolog/monolog", + "version": "3.9.0", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" + "Monolog\\": "src/Monolog" } }, "notification-url": "https://packagist.org/downloads/", @@ -1283,56 +2016,95 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" } ], - "description": "Common interfaces for simple caching", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" + "log", + "logging", + "psr-3" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, - "time": "2021-10-29T13:26:27+00:00" + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" }, { - "name": "symfony/clock", - "version": "v7.2.0", + "name": "nesbot/carbon", + "version": "3.10.2", "source": { "type": "git", - "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", + "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", "shasum": "" }, "require": { - "php": ">=8.2", + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "symfony/clock": "^6.3.12 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" }, "provide": { "psr/clock-implementation": "1.0" }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.75.0", + "kylekatarnls/multi-tester": "^2.5.3", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpunit/phpunit": "^10.5.46", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "bin": [ + "bin/carbon" + ], "type": "library", - "autoload": { - "files": [ - "Resources/now.php" - ], - "psr-4": { - "Symfony\\Component\\Clock\\": "" + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] }, - "exclude-from-classmap": [ - "/Tests/" - ] + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1340,164 +2112,241 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" } ], - "description": "Decouples applications from the system clock", - "homepage": "https://symfony.com", + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", "keywords": [ - "clock", - "psr20", + "date", + "datetime", "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" }, { - "url": "https://github.com/fabpot", - "type": "github" + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-08-02T09:36:06+00:00" }, { - "name": "symfony/console", - "version": "v7.2.5", + "name": "nette/schema", + "version": "v1.3.2", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88" + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "nette/utils": "^4.0", + "php": "8.1 - 8.4" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", "keywords": [ - "cli", - "command-line", - "console", - "terminal" + "config", + "nette" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.5" + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ { - "url": "https://github.com/fabpot", - "type": "github" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "name": "Nette Community", + "homepage": "https://nette.org/contributors" } ], - "time": "2025-03-12T08:11:12+00:00" + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.8" + }, + "time": "2025-08-06T21:43:34+00:00" }, { - "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "name": "nunomaduro/termwind", + "version": "v2.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { - "php": ">=8.1" + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { "files": [ - "function.php" - ] + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1505,852 +2354,6295 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", + "url": "https://www.paypal.com/paypalme/enunomaduro", "type": "custom" }, { - "url": "https://github.com/fabpot", + "url": "https://github.com/nunomaduro", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "url": "https://github.com/xiCO2k", + "type": "github" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-05-08T08:14:37+00:00" }, { - "name": "symfony/finder", - "version": "v7.2.2", + "name": "phpoption/phpoption", + "version": "1.9.4", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", "shasum": "" }, "require": { - "php": ">=8.2" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "PhpOption\\": "src/PhpOption/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" } ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.4" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/GrahamCampbell", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2025-08-21T11:53:16+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "name": "psr/clock", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.9.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.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.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.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.0" + }, + "time": "2025-06-25T14:20:11+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-25T06:35:40+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-07T08:17:57+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-20T08:04:18+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-29T08:23:45+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-08T02:45:35+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" + }, + { + "name": "symfony/polyfill-php85", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php85\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-23T16:12:55+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-18T09:42:54+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:36:08+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-25T06:35:40+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/e0837b4cbcef63c754d89a4806575cada743a38d", + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-01T21:02:37+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-27T08:32:26+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T19:55:54+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "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" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/semver", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + } + ], + "time": "2025-08-20T19:15:30+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-08-08T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "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": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.12.27", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "dev", + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-06-05T13:55:57+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.6.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + }, + "time": "2025-08-13T20:13:15+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.2", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", + "php": "^8.2.0", + "symfony/console": "^7.3.0" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-06-25T02:12:12+00:00" + }, + { + "name": "orchestra/canvas", + "version": "v10.0.2", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas.git", + "reference": "94f732350e5c6d7136ff7b0fd05a90079dd77deb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas/zipball/94f732350e5c6d7136ff7b0fd05a90079dd77deb", + "reference": "94f732350e5c6d7136ff7b0fd05a90079dd77deb", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^12.3.0", + "illuminate/database": "^12.3.0", + "illuminate/filesystem": "^12.3.0", + "illuminate/support": "^12.3.0", + "orchestra/canvas-core": "^10.0.1", + "orchestra/sidekick": "^1.1.0", + "orchestra/testbench-core": "^10.1.0", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31", + "symfony/yaml": "^7.2.0" + }, + "require-dev": { + "laravel/framework": "^12.3.0", + "laravel/pint": "^1.21", + "mockery/mockery": "^1.6.12", + "phpstan/phpstan": "^2.1.8", + "phpunit/phpunit": "^11.5.13", + "spatie/laravel-ray": "^1.40.1" + }, + "bin": [ + "canvas" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Orchestra\\Canvas\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas/tree/v10.0.2" + }, + "time": "2025-04-05T16:01:25+00:00" + }, + { + "name": "orchestra/canvas-core", + "version": "v10.0.1", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas-core.git", + "reference": "22b6515e7a070e1c45c8a3a9819f8b6cb0234173" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas-core/zipball/22b6515e7a070e1c45c8a3a9819f8b6cb0234173", + "reference": "22b6515e7a070e1c45c8a3a9819f8b6cb0234173", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^12.0", + "illuminate/support": "^12.0", + "orchestra/sidekick": "^1.0.2", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31" + }, + "require-dev": { + "laravel/framework": "^12.0", + "laravel/pint": "^1.21", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.0", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^11.5.7", + "symfony/yaml": "^7.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Orchestra\\Canvas\\Core\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\Core\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators Builder for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas-core/tree/v10.0.1" + }, + "time": "2025-02-19T04:17:05+00:00" + }, + { + "name": "orchestra/sidekick", + "version": "v1.2.14", + "source": { + "type": "git", + "url": "https://github.com/orchestral/sidekick.git", + "reference": "0f7d1d96d390e7bf9118f280dfae74b8b2fb0a00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/sidekick/zipball/0f7d1d96d390e7bf9118f280dfae74b8b2fb0a00", + "reference": "0f7d1d96d390e7bf9118f280dfae74b8b2fb0a00", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "php": "^8.1", + "symfony/polyfill-php83": "^1.32" + }, + "require-dev": { + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.48.29|^11.44.7|^12.1.1|^13.0", + "laravel/pint": "^1.4", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.37.0|^9.14.0|^10.0|^11.0", + "phpstan/phpstan": "^2.1.14", + "phpunit/phpunit": "^10.0|^11.0|^12.0", + "symfony/process": "^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Eloquent/functions.php", + "src/Http/functions.php", + "src/functions.php" + ], + "psr-4": { + "Orchestra\\Sidekick\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Packages Toolkit Utilities and Helpers for Laravel", + "support": { + "issues": "https://github.com/orchestral/sidekick/issues", + "source": "https://github.com/orchestral/sidekick/tree/v1.2.14" + }, + "time": "2025-08-06T23:54:27+00:00" + }, + { + "name": "orchestra/testbench", + "version": "v10.6.0", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench.git", + "reference": "87a7cb58edcfea9b1f26a63761c4d7ed5448f560" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/87a7cb58edcfea9b1f26a63761c4d7ed5448f560", + "reference": "87a7cb58edcfea9b1f26a63761c4d7ed5448f560", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.23", + "laravel/framework": "^12.24.0", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.6.1", + "orchestra/workbench": "^10.0.6", + "php": "^8.2", + "phpunit/phpunit": "^11.5.3|^12.0.1", + "symfony/process": "^7.2", + "symfony/yaml": "^7.2", + "vlucas/phpdotenv": "^5.6.1" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Laravel Testing Helper for Packages Development", + "homepage": "https://packages.tools/testbench/", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench/tree/v10.6.0" + }, + "time": "2025-08-20T14:38:08+00:00" + }, + { + "name": "orchestra/testbench-core", + "version": "v10.6.3", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench-core.git", + "reference": "5d263f59c283bd25879d7c71c7a2e8839980287e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/5d263f59c283bd25879d7c71c7a2e8839980287e", + "reference": "5d263f59c283bd25879d7c71c7a2e8839980287e", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "orchestra/sidekick": "~1.1.16|^1.2.12", + "php": "^8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-php83": "^1.32" + }, + "conflict": { + "brianium/paratest": "<7.3.0|>=8.0.0", + "laravel/framework": "<12.8.0|>=13.0.0", + "laravel/serializable-closure": "<1.3.0|>=2.0.0 <2.0.3|>=3.0.0", + "nunomaduro/collision": "<8.0.0|>=9.0.0", + "phpunit/phpunit": "<10.5.35|>=11.0.0 <11.5.3|12.0.0|>=12.4.0" + }, + "require-dev": { + "fakerphp/faker": "^1.24", + "laravel/framework": "^12.8.0", + "laravel/pint": "^1.24", + "laravel/serializable-closure": "^1.3|^2.0.4", + "mockery/mockery": "^1.6.10", + "phpstan/phpstan": "^2.1.19", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "spatie/laravel-ray": "^1.40.2", + "symfony/process": "^7.2.0", + "symfony/yaml": "^7.2.0", + "vlucas/phpdotenv": "^5.6.1" + }, + "suggest": { + "brianium/paratest": "Allow using parallel testing (^7.3).", + "ext-pcntl": "Required to use all features of the console signal trapping.", + "fakerphp/faker": "Allow using Faker for testing (^1.23).", + "laravel/framework": "Required for testing (^12.8.0).", + "mockery/mockery": "Allow using Mockery for testing (^1.6).", + "nunomaduro/collision": "Allow using Laravel style tests output and parallel testing (^8.0).", + "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^10.0).", + "phpunit/phpunit": "Allow using PHPUnit for testing (^10.5.35|^11.5.3|^12.0.1).", + "symfony/process": "Required to use Orchestra\\Testbench\\remote function (^7.2).", + "symfony/yaml": "Required for Testbench CLI (^7.2).", + "vlucas/phpdotenv": "Required for Testbench CLI (^5.6.1)." + }, + "bin": [ + "testbench" + ], + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Orchestra\\Testbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Testing Helper for Laravel Development", + "homepage": "https://packages.tools/testbench", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench-core" + }, + "time": "2025-08-27T23:59:57+00:00" + }, + { + "name": "orchestra/workbench", + "version": "v10.0.6", + "source": { + "type": "git", + "url": "https://github.com/orchestral/workbench.git", + "reference": "4e8a5a68200971ddb9ce4abf26488838bf5c0812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/workbench/zipball/4e8a5a68200971ddb9ce4abf26488838bf5c0812", + "reference": "4e8a5a68200971ddb9ce4abf26488838bf5c0812", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.23", + "laravel/framework": "^12.1.1", + "laravel/pail": "^1.2.2", + "laravel/tinker": "^2.10.1", + "nunomaduro/collision": "^8.6", + "orchestra/canvas": "^10.0.2", + "orchestra/sidekick": "^1.1.0", + "orchestra/testbench-core": "^10.2.1", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.2", + "symfony/yaml": "^7.2" + }, + "require-dev": { + "laravel/pint": "^1.21.2", + "mockery/mockery": "^1.6.12", + "phpstan/phpstan": "^2.1.8", + "phpunit/phpunit": "^11.5.3|^12.0.1", + "spatie/laravel-ray": "^1.40.1" + }, + "suggest": { + "ext-pcntl": "Required to use all features of the console signal trapping." + }, + "type": "library", + "autoload": { + "psr-4": { + "Orchestra\\Workbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Workbench Companion for Laravel Packages Development", + "keywords": [ + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/workbench/issues", + "source": "https://github.com/orchestral/workbench/tree/v10.0.6" + }, + "time": "2025-04-13T01:07:44+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.11", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4", + "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.2" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.11" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-08-27T14:37:49+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.35", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "d341ee94ee5007b286fc7907b383aae6b5b3cc91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d341ee94ee5007b286fc7907b383aae6b5b3cc91", + "reference": "d341ee94ee5007b286fc7907b383aae6b5b3cc91", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.11", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.2", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.35" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-08-28T05:13:54+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.10", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "https://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.10" + }, + "time": "2025-08-04T12:39:37+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85c77556683e6eee4323e4c5468641ca0237e2e8", + "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2025-08-10T08:07:46+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, - "suggest": { - "ext-ctype": "For best performance" + "require-dev": { + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-main": "6.1-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "export", + "exporter" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "name": "sebastian/global-state", + "version": "7.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, - "suggest": { - "ext-intl": "For best performance" + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-main": "7.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" + "global state" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "name": "sebastian/lines-of-code", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "php": ">=7.2" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, - "suggest": { - "ext-intl": "For best performance" + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-main": "3.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "classmap": [ - "Resources/stubs" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "name": "sebastian/object-enumerator", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, - "suggest": { - "ext-mbstring": "For best performance" + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-main": "6.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { - "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "name": "sebastian/object-reflector", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-main": "4.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, "classmap": [ - "Resources/stubs" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { - "name": "symfony/process", - "version": "v7.2.5", + "name": "sebastian/recursion-context", + "version": "6.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { "php": ">=8.2" }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" }, { - "url": "https://github.com/fabpot", - "type": "github" + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.5.1", + "name": "sebastian/type", + "version": "5.1.3", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2" }, - "conflict": { - "ext-psr": "<1.1|>=2" + "require-dev": { + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "5.1-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/sebastianbergmann", + "type": "github" }, { - "url": "https://github.com/fabpot", - "type": "github" + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { - "name": "symfony/string", - "version": "v7.2.0", + "name": "sebastian/version", + "version": "5.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "php": ">=8.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { - "name": "symfony/translation", - "version": "v7.2.4", + "name": "staabm/side-effects-detector", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", - "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" - }, - "provide": { - "symfony/translation-implementation": "2.3|3.0" + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" ], - "description": "Provides tools to internationalize your application", - "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.4" + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/staabm", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2024-10-20T05:08:20+00:00" }, { - "name": "symfony/translation-contracts", - "version": "v3.5.1", + "name": "symfony/yaml", + "version": "v7.3.3", "source": { "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "url": "https://github.com/symfony/yaml.git", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.5-dev" - } + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", "autoload": { "psr-4": { - "Symfony\\Contracts\\Translation\\": "" + "Symfony\\Component\\Yaml\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2359,26 +8651,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to translation", + "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/yaml/tree/v7.3.3" }, "funding": [ { @@ -2389,89 +8673,68 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-08-27T11:34:33+00:00" }, { - "name": "voku/portable-ascii", - "version": "2.0.3", + "name": "theseer/tokenizer", + "version": "1.2.3", "source": { "type": "git", - "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { - "php": ">=7.0.0" - }, - "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" - }, - "suggest": { - "ext-intl": "Use Intl for transliterator_transliterate() support" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "voku\\": "src/voku/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Lars Moelleken", - "homepage": "https://www.moelleken.org/" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", - "homepage": "https://github.com/voku/portable-ascii", - "keywords": [ - "ascii", - "clean", - "php" - ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { - "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { - "url": "https://www.paypal.me/moelleken", - "type": "custom" - }, - { - "url": "https://github.com/voku", + "url": "https://github.com/theseer", "type": "github" - }, - { - "url": "https://opencollective.com/portable-ascii", - "type": "open_collective" - }, - { - "url": "https://www.patreon.com/voku", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", - "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "dev", "stability-flags": {}, diff --git a/docs/index.html b/docs/index.html index 564d802..b99a8c4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -64,6 +64,7 @@ border-radius: 5px; overflow-x: auto; margin: 20px 0; + white-space: pre-wrap; } .highlight { background: #f39c12; @@ -151,6 +152,37 @@

📊 Performance Benefits

  • Improved application response times
  • +

    🧪 Real-World Test Results

    +

    We recently ran comprehensive feature tests inside a real Laravel project. Here's what SmartCache delivered:

    + +
    +
    +

    ✅ Core Operations

    +

    Basic Operations: put, get, forget all worked as expected, with helper functions fully supported.

    +
    +
    +

    ✅ Advanced Features

    +

    Compression & Chunking: 2,000 records stored and retrieved with 100% data integrity. 5,000 records handled seamlessly using chunking.

    +
    +
    +

    ✅ Smart Caching

    +

    Remember Function: Expensive operations cached properly, saving significant execution time on subsequent calls.

    +
    +
    +

    ✅ Driver Compatibility

    +

    Multi-Driver Support: Redis, File, Database, and Array drivers all passed with compression and chunking enabled.

    +
    +
    + +

    ⚡ Performance Comparison

    +

    Storing ~500KB dataset in a production environment:

    +
    +Laravel SmartCache → Store: 9.3ms, Retrieve: 3.5ms +Laravel Cache → Store: 3.6ms, Retrieve: 8.5ms + +👉 SmartCache trades a slightly slower write for much faster reads! +
    +
    📚 View Documentation 📥 Download Latest diff --git a/examples/usage.php b/examples/usage.php deleted file mode 100644 index cc84b48..0000000 --- a/examples/usage.php +++ /dev/null @@ -1,48 +0,0 @@ -whereHas('roles') - ->get(); -}); - -// Dependency Injection example -class UserService -{ - protected $cache; - - public function __construct(\SmartCache\Contracts\SmartCache $cache) - { - $this->cache = $cache; - } - - public function getAllUsers() - { - return $this->cache->remember('all_users', 3600, function () { - return User::with('relations')->get(); - }); - } -} - -// Clearing specific keys -SmartCache::forget('large-array'); - -// Clearing all SmartCache managed keys -// This is useful when you want to clear only SmartCache items without affecting other cache -SmartCache::clear(); \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..338fabe --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,34 @@ + + + + + ./tests/Unit + + + ./tests/Feature + + + + + ./src + + + ./src/Console + ./src/helpers.php + + + + + + + + + diff --git a/src/Providers/SmartCacheServiceProvider.php b/src/Providers/SmartCacheServiceProvider.php index 1d95200..488a3f1 100644 --- a/src/Providers/SmartCacheServiceProvider.php +++ b/src/Providers/SmartCacheServiceProvider.php @@ -24,7 +24,7 @@ public function register(): void // Register the service $this->app->singleton(SmartCacheContract::class, function ($app) { - $cache = $app['cache']; + $cacheManager = $app['cache']; $config = $app['config']; // Create strategies based on config @@ -44,7 +44,7 @@ public function register(): void ); } - return new SmartCache($cache->store(), $config, $strategies); + return new SmartCache($cacheManager->store(), $cacheManager, $config, $strategies); }); // Register alias for facade @@ -58,7 +58,7 @@ public function boot(): void { // Publish config $this->publishes([ - __DIR__ . '/../../config/smart-cache.php' => config_path('smart-cache.php'), + __DIR__ . '/../../config/smart-cache.php' => $this->app->configPath('smart-cache.php'), ], 'smart-cache-config'); // Register commands diff --git a/src/SmartCache.php b/src/SmartCache.php index 4e63105..bcdf7af 100644 --- a/src/SmartCache.php +++ b/src/SmartCache.php @@ -3,6 +3,7 @@ namespace SmartCache; use Illuminate\Contracts\Cache\Repository; +use Illuminate\Contracts\Cache\Factory as CacheManager; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Support\Facades\Log; use SmartCache\Contracts\OptimizationStrategy; @@ -15,6 +16,11 @@ class SmartCache implements SmartCacheContract */ protected Repository $cache; + /** + * @var CacheManager + */ + protected CacheManager $cacheManager; + /** * @var ConfigRepository */ @@ -39,12 +45,14 @@ class SmartCache implements SmartCacheContract * SmartCache constructor. * * @param Repository $cache + * @param CacheManager $cacheManager * @param ConfigRepository $config * @param array $strategies */ - public function __construct(Repository $cache, ConfigRepository $config, array $strategies = []) + public function __construct(Repository $cache, CacheManager $cacheManager, ConfigRepository $config, array $strategies = []) { $this->cache = $cache; + $this->cacheManager = $cacheManager; $this->config = $config; foreach ($strategies as $strategy) { @@ -178,7 +186,11 @@ public function rememberForever(string $key, \Closure $callback): mixed */ public function store(string $name = null): Repository { - return $this->cache->store($name); + if ($name === null) { + return $this->cache; + } + + return $this->cacheManager->store($name); } /** diff --git a/src/helpers.php b/src/helpers.php index 01771df..65c994d 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -18,7 +18,7 @@ function smart_cache() $arguments = func_get_args(); if (empty($arguments)) { - return app('smart-cache'); + return function_exists('app') ? app('smart-cache') : \Illuminate\Container\Container::getInstance()->make('smart-cache'); } if (is_string($arguments[0])) { diff --git a/tests/Feature/SmartCacheIntegrationTest.php b/tests/Feature/SmartCacheIntegrationTest.php new file mode 100644 index 0000000..1286cb1 --- /dev/null +++ b/tests/Feature/SmartCacheIntegrationTest.php @@ -0,0 +1,351 @@ +smartCache = $this->app->make(SmartCache::class); + } + + public function test_full_workflow_with_compression_and_retrieval() + { + // Test the complete workflow: store large data, ensure it's compressed, retrieve it + $key = 'integration-compression-test'; + $largeData = $this->createCompressibleData(); + + // Store the data + $this->assertTrue($this->smartCache->put($key, $largeData, 3600)); + + // Verify it's tracked as optimized + $managedKeys = $this->smartCache->getManagedKeys(); + $this->assertContains($key, $managedKeys); + + // Verify we can retrieve the original data + $retrieved = $this->smartCache->get($key); + $this->assertEquals($largeData, $retrieved); + + // Verify the raw cache entry is compressed + $rawCached = Cache::get($key); + $this->assertIsArray($rawCached); + $this->assertArrayHasKey('_sc_compressed', $rawCached); + $this->assertTrue($rawCached['_sc_compressed']); + + // Clean up + $this->smartCache->forget($key); + $this->assertFalse($this->smartCache->has($key)); + } + + public function test_full_workflow_with_chunking_and_retrieval() + { + // Disable compression for this test to ensure chunking is applied + $this->app['config']->set('smart-cache.strategies.compression.enabled', false); + + // Create a fresh SmartCache instance with chunking only + $chunkingSmartCache = new \SmartCache\SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [new \SmartCache\Strategies\ChunkingStrategy(2048, 100)] + ); + + // Test chunking workflow + $key = 'integration-chunking-test'; + $largeArray = $this->createChunkableData(); + + // Store the data + $this->assertTrue($chunkingSmartCache->put($key, $largeArray, 3600)); + + // Verify it's tracked as optimized + $managedKeys = $chunkingSmartCache->getManagedKeys(); + $this->assertContains($key, $managedKeys); + + // Verify we can retrieve the original data + $retrieved = $chunkingSmartCache->get($key); + $this->assertEquals($largeArray, $retrieved); + + // Verify the raw cache entry is chunked + $rawCached = Cache::get($key); + $this->assertIsArray($rawCached); + $this->assertArrayHasKey('_sc_chunked', $rawCached); + $this->assertTrue($rawCached['_sc_chunked']); + + // Verify chunk keys exist in cache + foreach ($rawCached['chunk_keys'] as $chunkKey) { + $this->assertTrue(Cache::has($chunkKey)); + } + + // Clean up + $chunkingSmartCache->forget($key); + $this->assertFalse($chunkingSmartCache->has($key)); + + // Verify chunk keys are also cleaned up + foreach ($rawCached['chunk_keys'] as $chunkKey) { + $this->assertFalse(Cache::has($chunkKey)); + } + } + + public function test_remember_method_integration() + { + $key = 'integration-remember-test'; + $callCount = 0; + + $callback = function () use (&$callCount) { + $callCount++; + return $this->createCompressibleData(); // Large data that should be compressed + }; + + // First call should execute callback and store compressed data + $result1 = $this->smartCache->remember($key, 3600, $callback); + $this->assertEquals(1, $callCount); + + // Verify it's optimized + $managedKeys = $this->smartCache->getManagedKeys(); + $this->assertContains($key, $managedKeys); + + // Second call should retrieve from cache without executing callback + $result2 = $this->smartCache->remember($key, 3600, $callback); + $this->assertEquals(1, $callCount); // Should not increment + $this->assertEquals($result1, $result2); + + // Clean up + $this->smartCache->forget($key); + } + + public function test_remember_forever_integration() + { + $key = 'integration-remember-forever-test'; + + $result = $this->smartCache->rememberForever($key, function () { + return $this->createLargeTestData(100); + }); + + // Should be retrievable + $retrieved = $this->smartCache->get($key); + $this->assertEquals($result, $retrieved); + + // Should be optimized + $managedKeys = $this->smartCache->getManagedKeys(); + $this->assertContains($key, $managedKeys); + + // Clean up + $this->smartCache->forget($key); + } + + public function test_mixed_data_types_integration() + { + // Test storing different types of data + $testCases = [ + 'string-small' => 'small string', + 'string-large' => $this->createCompressibleData(), + 'array-small' => ['key' => 'value'], + 'array-large' => $this->createLargeTestData(50), + 'array-chunked' => $this->createChunkableData(), + 'integer' => 42, + 'float' => 3.14159, + 'boolean' => true, + 'null' => null, + ]; + + // Store all test cases + foreach ($testCases as $key => $value) { + $this->assertTrue($this->smartCache->put($key, $value, 3600)); + } + + // Verify all can be retrieved correctly + foreach ($testCases as $key => $originalValue) { + $retrievedValue = $this->smartCache->get($key); + $this->assertEquals($originalValue, $retrievedValue, "Failed for key: $key"); + } + + // Check which ones are managed (optimized) + $managedKeys = $this->smartCache->getManagedKeys(); + + // Large string and arrays should be managed + $this->assertContains('string-large', $managedKeys); + $this->assertContains('array-large', $managedKeys); + $this->assertContains('array-chunked', $managedKeys); + + // Small values should not be managed + $this->assertNotContains('string-small', $managedKeys); + $this->assertNotContains('array-small', $managedKeys); + $this->assertNotContains('integer', $managedKeys); + + // Clean up + foreach (array_keys($testCases) as $key) { + $this->smartCache->forget($key); + } + } + + public function test_cache_clear_integration() + { + // Store multiple optimized items + $keys = []; + for ($i = 0; $i < 5; $i++) { + $key = "clear-test-$i"; + $keys[] = $key; + $this->smartCache->put($key, $this->createCompressibleData()); + } + + // Verify all are managed + $managedKeys = $this->smartCache->getManagedKeys(); + foreach ($keys as $key) { + $this->assertContains($key, $managedKeys); + } + + // Clear all + $this->assertTrue($this->smartCache->clear()); + + // Verify all are gone + $this->assertEmpty($this->smartCache->getManagedKeys()); + foreach ($keys as $key) { + $this->assertFalse($this->smartCache->has($key)); + } + } + + public function test_concurrent_access_simulation() + { + // Simulate concurrent access patterns + $baseKey = 'concurrent-test'; + + // Simulate multiple "processes" storing and retrieving data + for ($process = 0; $process < 3; $process++) { + $key = "{$baseKey}-{$process}"; + $data = $this->createLargeTestData(100 + $process * 10); + + // Store + $this->assertTrue($this->smartCache->put($key, $data)); + + // Immediate retrieval + $retrieved = $this->smartCache->get($key); + $this->assertEquals($data, $retrieved); + + // Verify optimization + $this->assertTrue($this->smartCache->has($key)); + } + + // Clean up + for ($process = 0; $process < 3; $process++) { + $key = "{$baseKey}-{$process}"; + $this->smartCache->forget($key); + } + } + + public function test_fallback_behavior_integration() + { + // This tests the fallback behavior when strategies fail + // Since we can't easily make strategies fail in integration tests, + // we'll test that the system gracefully handles edge cases + + // Test with empty data + $this->assertTrue($this->smartCache->put('empty-string', '')); + $this->assertEquals('', $this->smartCache->get('empty-string')); + + // Test with empty array + $this->assertTrue($this->smartCache->put('empty-array', [])); + $this->assertEquals([], $this->smartCache->get('empty-array')); + + // Test with very large single string (might challenge compression) + $veryLargeString = str_repeat('x', 1000000); // 1MB of 'x' + $this->assertTrue($this->smartCache->put('very-large', $veryLargeString)); + $this->assertEquals($veryLargeString, $this->smartCache->get('very-large')); + + // Clean up + $this->smartCache->forget('empty-string'); + $this->smartCache->forget('empty-array'); + $this->smartCache->forget('very-large'); + } + + public function test_cache_store_switching() + { + // Test using different cache stores + $defaultStore = $this->smartCache->store(); + $arrayStore = $this->smartCache->store('array'); + + // Store in default store + $defaultStore->put('default-key', 'default-value'); + + // Store in array store + $arrayStore->put('array-key', 'array-value'); + + // Values should be accessible from their respective stores + $this->assertTrue($defaultStore->has('default-key')); + $this->assertTrue($arrayStore->has('array-key')); + + // Verify values are correct + $this->assertEquals('default-value', $defaultStore->get('default-key')); + $this->assertEquals('array-value', $arrayStore->get('array-key')); + + // Clean up + $defaultStore->forget('default-key'); + $arrayStore->forget('array-key'); + } + + public function test_performance_characteristics() + { + // Simple performance test to ensure operations complete reasonably quickly + $startTime = microtime(true); + + // Perform a series of operations + for ($i = 0; $i < 10; $i++) { + $key = "perf-test-$i"; + $data = $this->createLargeTestData(50); // Moderate size data + + $this->smartCache->put($key, $data); + $retrieved = $this->smartCache->get($key); + $this->assertEquals($data, $retrieved); + $this->smartCache->forget($key); + } + + $endTime = microtime(true); + $duration = $endTime - $startTime; + + // Should complete in reasonable time (adjust threshold as needed) + $this->assertLessThan(5.0, $duration, 'Performance test took too long: ' . $duration . ' seconds'); + } + + public function test_memory_usage_with_large_datasets() + { + $initialMemory = memory_get_usage(); + + // Store and retrieve several large datasets + $keys = []; + for ($i = 0; $i < 5; $i++) { + $key = "memory-test-$i"; + $keys[] = $key; + + $largeData = $this->createLargeTestData(200); + $this->smartCache->put($key, $largeData); + + // Verify retrieval + $retrieved = $this->smartCache->get($key); + $this->assertEquals($largeData, $retrieved); + } + + $afterStoreMemory = memory_get_usage(); + + // Clean up + foreach ($keys as $key) { + $this->smartCache->forget($key); + } + + $finalMemory = memory_get_usage(); + + // Memory usage should be reasonable (this is more of a smoke test) + $memoryIncrease = $afterStoreMemory - $initialMemory; + $this->assertLessThan(50 * 1024 * 1024, $memoryIncrease, 'Memory usage increased too much: ' . ($memoryIncrease / 1024 / 1024) . ' MB'); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..fb031ee --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,198 @@ +loadPackageConfiguration(); + } + + /** + * Get package providers. + * + * @param \Illuminate\Foundation\Application $app + * @return array + */ + protected function getPackageProviders($app): array + { + return [ + SmartCacheServiceProvider::class, + ]; + } + + /** + * Define aliases. + * + * @param \Illuminate\Foundation\Application $app + * @return array + */ + protected function getPackageAliases($app): array + { + return [ + 'SmartCache' => \SmartCache\Facades\SmartCache::class, + ]; + } + + /** + * Define environment setup. + * + * @param \Illuminate\Foundation\Application $app + */ + protected function defineEnvironment($app): void + { + // Setup the application environment + $app['config']->set('app.key', 'base64:' . base64_encode(random_bytes(32))); + $app['config']->set('app.debug', true); + + // Setup cache configuration + $app['config']->set('cache.default', 'array'); + $app['config']->set('cache.stores.array', [ + 'driver' => 'array', + 'serialize' => false, + ]); + + $app['config']->set('cache.stores.file', [ + 'driver' => 'file', + 'path' => __DIR__ . '/storage/framework/cache', + ]); + + // Setup SmartCache configuration + $app['config']->set('smart-cache', [ + 'strategies' => [ + 'compression' => [ + 'enabled' => true, + 'level' => 6, + ], + 'chunking' => [ + 'enabled' => true, + 'chunk_size' => 1000, + ], + ], + 'thresholds' => [ + 'compression' => 1024, // 1KB for testing (lower than default) + 'chunking' => 2048, // 2KB for testing (lower than default) + ], + 'fallback' => [ + 'enabled' => true, + 'log_errors' => false, // Disable logging in tests + ], + ]); + } + + /** + * Load package configuration for testing. + */ + protected function loadPackageConfiguration(): void + { + // This method can be overridden in individual test classes + // to provide specific configuration for different test scenarios + } + + /** + * Get a cache manager instance for testing. + */ + protected function getCacheManager(): CacheManager + { + return $this->app['cache']; + } + + /** + * Get a specific cache store for testing. + */ + protected function getCacheStore(string $store = null) + { + return $this->getCacheManager()->store($store); + } + + /** + * Create a large test dataset for optimization testing. + */ + protected function createLargeTestData(int $size = 2000): array + { + $data = []; + for ($i = 0; $i < $size; $i++) { + $data[] = [ + 'id' => $i, + 'name' => 'Test Item ' . $i, + 'description' => str_repeat('Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', 10), + 'metadata' => [ + 'created_at' => now()->toISOString(), + 'tags' => ['tag1', 'tag2', 'tag3'], + 'nested' => [ + 'level1' => [ + 'level2' => [ + 'data' => str_repeat('nested data ', 20) + ] + ] + ] + ] + ]; + } + + return $data; + } + + /** + * Create test data that should trigger compression. + */ + protected function createCompressibleData(): string + { + // Create repetitive string that compresses well + return str_repeat('This is test data that should compress well. ', 100); + } + + /** + * Create test data that should trigger chunking. + */ + protected function createChunkableData(): array + { + return $this->createLargeTestData(1200); // Creates much larger data to ensure chunking threshold is met + } + + /** + * Assert that a value is optimized (not the original value). + */ + protected function assertValueIsOptimized($original, $cached): void + { + $this->assertNotEquals($original, $cached, 'Value should be optimized and different from original'); + } + + /** + * Assert that a value has compression metadata. + */ + protected function assertValueIsCompressed($value): void + { + $this->assertIsArray($value, 'Compressed value should be an array'); + $this->assertArrayHasKey('_sc_compressed', $value, 'Compressed value should have compression marker'); + $this->assertTrue($value['_sc_compressed'], 'Compression marker should be true'); + $this->assertArrayHasKey('data', $value, 'Compressed value should have data key'); + } + + /** + * Assert that a value has chunking metadata. + */ + protected function assertValueIsChunked($value): void + { + $this->assertIsArray($value, 'Chunked value should be an array'); + $this->assertArrayHasKey('_sc_chunked', $value, 'Chunked value should have chunking marker'); + $this->assertTrue($value['_sc_chunked'], 'Chunking marker should be true'); + $this->assertArrayHasKey('chunk_keys', $value, 'Chunked value should have chunk_keys'); + $this->assertArrayHasKey('total_items', $value, 'Chunked value should have total_items'); + } +} diff --git a/tests/Unit/Console/ClearCommandTest.php b/tests/Unit/Console/ClearCommandTest.php new file mode 100644 index 0000000..ec91da9 --- /dev/null +++ b/tests/Unit/Console/ClearCommandTest.php @@ -0,0 +1,177 @@ +mockSmartCache = Mockery::mock(SmartCache::class); + $this->command = new ClearCommand(); + + // Set up command tester using Symfony Console Application instead + $application = new \Symfony\Component\Console\Application(); + $application->add($this->command); + $this->commandTester = new CommandTester($this->command); + } + + public function test_command_has_correct_signature_and_description() + { + $this->assertEquals('smart-cache:clear', $this->command->getName()); + $this->assertEquals('Clear all SmartCache managed items', $this->command->getDescription()); + } + + public function test_clear_command_with_no_managed_keys() + { + // Setup mock to return empty array for managed keys + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn([]); + + // Inject the mock into the command + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('No SmartCache managed items found.', $output); + } + + public function test_clear_command_with_managed_keys_success() + { + $managedKeys = ['key1', 'key2', 'key3']; + + // Setup mock expectations + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn($managedKeys); + + $this->mockSmartCache->shouldReceive('clear') + ->once() + ->andReturn(true); + + // Inject the mock into the command + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Clearing 3 SmartCache managed items...', $output); + $this->assertStringContainsString('All SmartCache items have been cleared successfully.', $output); + } + + public function test_clear_command_with_managed_keys_failure() + { + $managedKeys = ['key1', 'key2']; + + // Setup mock expectations + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn($managedKeys); + + $this->mockSmartCache->shouldReceive('clear') + ->once() + ->andReturn(false); + + // Inject the mock into the command + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert error exit code + $this->assertEquals(1, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Clearing 2 SmartCache managed items...', $output); + $this->assertStringContainsString('Some SmartCache items could not be cleared.', $output); + } + + public function test_clear_command_with_single_managed_key() + { + $managedKeys = ['single-key']; + + // Setup mock expectations + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn($managedKeys); + + $this->mockSmartCache->shouldReceive('clear') + ->once() + ->andReturn(true); + + // Inject the mock into the command + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Clearing 1 SmartCache managed items...', $output); + $this->assertStringContainsString('All SmartCache items have been cleared successfully.', $output); + } + + public function test_clear_command_integration_with_real_smart_cache() + { + // Use real SmartCache instance from service container + $smartCache = $this->app->make(\SmartCache\Contracts\SmartCache::class); + + // Add some test data + $smartCache->put('test-key-1', $this->createCompressibleData()); + $smartCache->put('test-key-2', $this->createLargeTestData(50)); + + // Verify keys are managed + $managedKeys = $smartCache->getManagedKeys(); + $this->assertNotEmpty($managedKeys); + + // Create command with Laravel application set + $command = new ClearCommand(); + $command->setLaravel($this->app); + + $commandTester = new CommandTester($command); + $exitCode = $commandTester->execute([]); + + // Assert success + $this->assertEquals(0, $exitCode); + + // Verify keys are cleared + $this->assertEmpty($smartCache->getManagedKeys()); + } + + protected function tearDown(): void + { + Mockery::close(); + parent::tearDown(); + } +} diff --git a/tests/Unit/Console/StatusCommandTest.php b/tests/Unit/Console/StatusCommandTest.php new file mode 100644 index 0000000..6e3c14c --- /dev/null +++ b/tests/Unit/Console/StatusCommandTest.php @@ -0,0 +1,318 @@ +mockSmartCache = Mockery::mock(SmartCache::class); + $this->mockConfig = Mockery::mock(ConfigRepository::class); + $this->command = new StatusCommand(); + + // Set up command tester using Symfony Console Application instead + $application = new Application(); + $application->add($this->command); + $this->commandTester = new CommandTester($this->command); + } + + public function test_command_has_correct_signature_and_description() + { + $this->assertEquals('smart-cache:status', $this->command->getName()); + $this->assertEquals('Display information about SmartCache usage and configuration', $this->command->getDescription()); + } + + public function test_status_command_with_no_managed_keys() + { + // Setup mocks + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn([]); + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($this->getDefaultSmartCacheConfig()); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('SmartCache Status', $output); + $this->assertStringContainsString('Managed Keys: 0', $output); + $this->assertStringContainsString('Cache Driver:', $output); + $this->assertStringContainsString('Compression: Enabled', $output); + $this->assertStringContainsString('Chunking: Enabled', $output); + } + + public function test_status_command_with_managed_keys() + { + $managedKeys = ['key1', 'key2', 'key3', 'key4', 'key5', 'key6', 'key7']; + + // Setup mocks + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn($managedKeys); + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($this->getDefaultSmartCacheConfig()); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Managed Keys: 7', $output); + $this->assertStringContainsString('Examples:', $output); + $this->assertStringContainsString('key1', $output); + $this->assertStringContainsString('key2', $output); + $this->assertStringContainsString('key3', $output); + $this->assertStringContainsString('key4', $output); + $this->assertStringContainsString('key5', $output); + $this->assertStringContainsString('and 2 more', $output); + } + + public function test_status_command_with_few_managed_keys() + { + $managedKeys = ['key1', 'key2', 'key3']; + + // Setup mocks + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn($managedKeys); + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($this->getDefaultSmartCacheConfig()); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Managed Keys: 3', $output); + $this->assertStringContainsString('Examples:', $output); + $this->assertStringContainsString('key1', $output); + $this->assertStringContainsString('key2', $output); + $this->assertStringContainsString('key3', $output); + $this->assertStringNotContainsString('and', $output); // No "and X more" message + } + + public function test_status_command_displays_configuration_correctly() + { + $customConfig = [ + 'strategies' => [ + 'compression' => [ + 'enabled' => false, + 'level' => 9 + ], + 'chunking' => [ + 'enabled' => true, + 'chunk_size' => 1000 + ] + ], + 'thresholds' => [ + 'compression' => 2048, // 2KB + 'chunking' => 4096 // 4KB + ] + ]; + + // Setup mocks + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn([]); + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($customConfig); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Compression: Disabled', $output); + $this->assertStringContainsString('Threshold: 2.00 KB', $output); + $this->assertStringContainsString('Level: 9', $output); + $this->assertStringContainsString('Chunking: Enabled', $output); + $this->assertStringContainsString('Threshold: 4.00 KB', $output); + } + + public function test_status_command_displays_cache_driver() + { + // Setup mocks + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn([]); + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($this->getDefaultSmartCacheConfig()); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Assert success exit code + $this->assertEquals(0, $exitCode); + + // Assert correct output + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Cache Driver: array', $output); // Default test driver + } + + public function test_status_command_integration_with_real_dependencies() + { + // Use real dependencies from service container + $smartCache = $this->app->make(\SmartCache\Contracts\SmartCache::class); + + // Add some test data + $smartCache->put('integration-test-key', $this->createCompressibleData()); + + // Create command with Laravel application set + $command = new StatusCommand(); + $command->setLaravel($this->app); + + $commandTester = new CommandTester($command); + $exitCode = $commandTester->execute([]); + + // Assert success + $this->assertEquals(0, $exitCode); + + // Verify output contains expected elements + $output = $commandTester->getDisplay(); + $this->assertStringContainsString('SmartCache Status', $output); + $this->assertStringContainsString('Managed Keys:', $output); + $this->assertStringContainsString('Configuration:', $output); + + // Clean up + $smartCache->forget('integration-test-key'); + } + + public function test_status_command_handles_missing_config_gracefully() + { + // Setup mocks with minimal config + $this->mockSmartCache->shouldReceive('getManagedKeys') + ->once() + ->andReturn([]); + + $incompleteConfig = [ + 'strategies' => [ + 'compression' => ['enabled' => true, 'level' => 6], + 'chunking' => ['enabled' => true, 'chunk_size' => 1000] + ], + 'thresholds' => [ + 'compression' => 1024, + 'chunking' => 2048 + ] + ]; + + $this->mockConfig->shouldReceive('get') + ->with('smart-cache') + ->once() + ->andReturn($incompleteConfig); + + // Inject mocks + $this->command->setLaravel($this->app); + $this->app->instance(SmartCache::class, $this->mockSmartCache); + $this->app->instance(ConfigRepository::class, $this->mockConfig); + + // Execute the command + $exitCode = $this->commandTester->execute([]); + + // Should still complete successfully + $this->assertEquals(0, $exitCode); + + // Should display available configuration + $output = $this->commandTester->getDisplay(); + $this->assertStringContainsString('Configuration:', $output); + $this->assertStringContainsString('Compression: Enabled', $output); + $this->assertStringContainsString('Chunking: Enabled', $output); + } + + /** + * Get default smart cache configuration for testing. + */ + protected function getDefaultSmartCacheConfig(): array + { + return [ + 'strategies' => [ + 'compression' => [ + 'enabled' => true, + 'level' => 6 + ], + 'chunking' => [ + 'enabled' => true, + 'chunk_size' => 1000 + ] + ], + 'thresholds' => [ + 'compression' => 1024, + 'chunking' => 2048 + ] + ]; + } + + protected function tearDown(): void + { + Mockery::close(); + parent::tearDown(); + } +} diff --git a/tests/Unit/Providers/SmartCacheServiceProviderTest.php b/tests/Unit/Providers/SmartCacheServiceProviderTest.php new file mode 100644 index 0000000..e0cb310 --- /dev/null +++ b/tests/Unit/Providers/SmartCacheServiceProviderTest.php @@ -0,0 +1,277 @@ +assertTrue($this->app->bound(SmartCacheContract::class)); + + // Should return the same instance on multiple calls + $instance1 = $this->app->make(SmartCacheContract::class); + $instance2 = $this->app->make(SmartCacheContract::class); + + $this->assertSame($instance1, $instance2); + $this->assertInstanceOf(SmartCache::class, $instance1); + } + + public function test_service_provider_registers_smart_cache_alias() + { + // The service should also be available via alias + $this->assertTrue($this->app->bound('smart-cache')); + + $instanceFromContract = $this->app->make(SmartCacheContract::class); + $instanceFromAlias = $this->app->make('smart-cache'); + + $this->assertSame($instanceFromContract, $instanceFromAlias); + } + + public function test_smart_cache_is_constructed_with_correct_dependencies() + { + $smartCache = $this->app->make(SmartCacheContract::class); + + // Should be able to use basic cache operations + $this->assertTrue($smartCache->put('test-key', 'test-value')); + $this->assertEquals('test-value', $smartCache->get('test-key')); + $this->assertTrue($smartCache->has('test-key')); + $this->assertTrue($smartCache->forget('test-key')); + } + + public function test_smart_cache_uses_compression_strategy_when_enabled() + { + // Compression is enabled in test configuration + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store a large compressible string + $largeData = $this->createCompressibleData(); + $smartCache->put('compression-test', $largeData); + + // Should be tracked as a managed key since it was optimized + $managedKeys = $smartCache->getManagedKeys(); + $this->assertContains('compression-test', $managedKeys); + + // Should be able to retrieve the original data + $retrieved = $smartCache->get('compression-test'); + $this->assertEquals($largeData, $retrieved); + } + + public function test_smart_cache_uses_chunking_strategy_when_enabled() + { + // Chunking is enabled in test configuration + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store a large array that should trigger chunking + $largeArray = $this->createChunkableData(); + $smartCache->put('chunking-test', $largeArray); + + // Should be tracked as a managed key since it was optimized + $managedKeys = $smartCache->getManagedKeys(); + $this->assertContains('chunking-test', $managedKeys); + + // Should be able to retrieve the original data + $retrieved = $smartCache->get('chunking-test'); + $this->assertEquals($largeArray, $retrieved); + } + + public function test_service_provider_respects_compression_configuration() + { + // Test with compression disabled + $this->app['config']->set('smart-cache.strategies.compression.enabled', false); + + // Re-register the service provider to pick up new config + $provider = new SmartCacheServiceProvider($this->app); + $provider->register(); + + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store compressible data - should not be optimized + $largeData = $this->createCompressibleData(); + $smartCache->put('no-compression-test', $largeData); + + // Should not be tracked since compression is disabled + $managedKeys = $smartCache->getManagedKeys(); + $this->assertNotContains('no-compression-test', $managedKeys); + } + + public function test_service_provider_respects_chunking_configuration() + { + // Test with both compression and chunking disabled + $this->app['config']->set('smart-cache.strategies.compression.enabled', false); + $this->app['config']->set('smart-cache.strategies.chunking.enabled', false); + + // Re-register the service provider to pick up new config + $provider = new SmartCacheServiceProvider($this->app); + $provider->register(); + + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store chunkable data - should not be optimized since both strategies are disabled + $largeArray = $this->createChunkableData(); + $smartCache->put('no-chunking-test', $largeArray); + + // Should not be tracked since both strategies are disabled + $managedKeys = $smartCache->getManagedKeys(); + $this->assertNotContains('no-chunking-test', $managedKeys); + } + + public function test_service_provider_uses_custom_compression_settings() + { + // Set custom compression settings + $this->app['config']->set('smart-cache.thresholds.compression', 500); // 500 bytes + $this->app['config']->set('smart-cache.strategies.compression.level', 9); // Max compression + + // Re-register the service provider + $provider = new SmartCacheServiceProvider($this->app); + $provider->register(); + + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store data that exceeds the lower threshold + $mediumData = str_repeat('test ', 150); // ~750 bytes + $smartCache->put('custom-compression-test', $mediumData); + + // Should be optimized with the lower threshold + $managedKeys = $smartCache->getManagedKeys(); + $this->assertContains('custom-compression-test', $managedKeys); + + // Should still retrieve original data + $retrieved = $smartCache->get('custom-compression-test'); + $this->assertEquals($mediumData, $retrieved); + } + + public function test_service_provider_uses_custom_chunking_settings() + { + // Set custom chunking settings + $this->app['config']->set('smart-cache.thresholds.chunking', 1024); // 1KB + $this->app['config']->set('smart-cache.strategies.chunking.chunk_size', 50); // 50 items per chunk + + // Re-register the service provider + $provider = new SmartCacheServiceProvider($this->app); + $provider->register(); + + $smartCache = $this->app->make(SmartCacheContract::class); + + // Store array that should trigger chunking with custom settings + $testArray = $this->createLargeTestData(100); // 100 items, should be chunked + $smartCache->put('custom-chunking-test', $testArray); + + // Should be optimized + $managedKeys = $smartCache->getManagedKeys(); + $this->assertContains('custom-chunking-test', $managedKeys); + + // Should retrieve original data + $retrieved = $smartCache->get('custom-chunking-test'); + $this->assertEquals($testArray, $retrieved); + } + + public function test_service_provider_registers_console_commands_in_console_environment() + { + // Simulate console environment + $this->app['env'] = 'testing'; // This should trigger console registration + + // Get all registered commands + $registeredCommands = []; + + // Mock the commands method to capture registered commands + $originalProvider = new SmartCacheServiceProvider($this->app); + + // Check that commands are available in artisan + $artisan = $this->app['Illuminate\Contracts\Console\Kernel']; + + // The commands should be registered and available + $clearCommand = $this->app->make(ClearCommand::class); + $statusCommand = $this->app->make(StatusCommand::class); + + $this->assertInstanceOf(ClearCommand::class, $clearCommand); + $this->assertInstanceOf(StatusCommand::class, $statusCommand); + + // Verify command signatures + $this->assertEquals('smart-cache:clear', $clearCommand->getName()); + $this->assertEquals('smart-cache:status', $statusCommand->getName()); + } + + public function test_service_provider_merges_configuration() + { + // The service provider should merge the package configuration + $config = $this->app['config']->get('smart-cache'); + + $this->assertIsArray($config); + $this->assertArrayHasKey('strategies', $config); + $this->assertArrayHasKey('thresholds', $config); + $this->assertArrayHasKey('compression', $config['strategies']); + $this->assertArrayHasKey('chunking', $config['strategies']); + } + + public function test_service_provider_config_publishing() + { + $provider = new SmartCacheServiceProvider($this->app); + + // Boot the provider to register publishable assets + $provider->boot(); + + // In a minimal test environment, we can't test the exact publishing mechanism + // but we can verify the provider boots without error and that configuration is available + $config = $this->app['config']->get('smart-cache'); + $this->assertNotEmpty($config); + + // This test mainly ensures the boot method works correctly + $this->assertTrue(true); + } + + public function test_multiple_smart_cache_instances_are_same_singleton() + { + $instance1 = $this->app->make(SmartCacheContract::class); + $instance2 = app(SmartCacheContract::class); + $instance3 = resolve(SmartCacheContract::class); + + $this->assertSame($instance1, $instance2); + $this->assertSame($instance2, $instance3); + } + + public function test_smart_cache_integrates_with_laravel_cache_manager() + { + $smartCache = $this->app->make(SmartCacheContract::class); + + // Should be able to access different cache stores + $defaultStore = $smartCache->store(); + $arrayStore = $smartCache->store('array'); + + $this->assertNotNull($defaultStore); + $this->assertNotNull($arrayStore); + + // Both should be usable for caching + $defaultStore->put('default-test', 'value'); + $arrayStore->put('array-test', 'value'); + + $this->assertTrue($defaultStore->has('default-test')); + $this->assertTrue($arrayStore->has('array-test')); + } + + public function test_service_provider_handles_missing_strategies_gracefully() + { + // Remove all strategies from config + $this->app['config']->set('smart-cache.strategies', []); + + // Re-register the service provider + $provider = new SmartCacheServiceProvider($this->app); + $provider->register(); + + $smartCache = $this->app->make(SmartCacheContract::class); + + // Should still work, just without optimizations + $this->assertTrue($smartCache->put('test-key', 'test-value')); + $this->assertEquals('test-value', $smartCache->get('test-key')); + + // No strategies means no managed keys + $this->assertEmpty($smartCache->getManagedKeys()); + } +} diff --git a/tests/Unit/SmartCacheTest.php b/tests/Unit/SmartCacheTest.php new file mode 100644 index 0000000..6d6aab6 --- /dev/null +++ b/tests/Unit/SmartCacheTest.php @@ -0,0 +1,347 @@ +smartCache = $this->app->make(\SmartCache\Contracts\SmartCache::class); + } + + public function test_can_store_and_retrieve_simple_value() + { + $key = 'test-key'; + $value = 'Simple test value'; + + $this->assertTrue($this->smartCache->put($key, $value)); + $this->assertEquals($value, $this->smartCache->get($key)); + $this->assertTrue($this->smartCache->has($key)); + } + + public function test_can_store_and_retrieve_array_value() + { + $key = 'test-array'; + $value = ['name' => 'John', 'age' => 30, 'city' => 'New York']; + + $this->assertTrue($this->smartCache->put($key, $value)); + $this->assertEquals($value, $this->smartCache->get($key)); + } + + public function test_get_returns_default_when_key_not_exists() + { + $default = 'default-value'; + $this->assertEquals($default, $this->smartCache->get('non-existent-key', $default)); + } + + public function test_can_use_remember_method() + { + $key = 'remember-key'; + $expectedValue = 'remembered-value'; + + $result = $this->smartCache->remember($key, 3600, function () use ($expectedValue) { + return $expectedValue; + }); + + $this->assertEquals($expectedValue, $result); + $this->assertEquals($expectedValue, $this->smartCache->get($key)); + } + + public function test_remember_returns_cached_value_on_subsequent_calls() + { + $key = 'remember-cached-key'; + $callCount = 0; + + $callback = function () use (&$callCount) { + $callCount++; + return 'value-' . $callCount; + }; + + // First call should execute callback + $result1 = $this->smartCache->remember($key, 3600, $callback); + $this->assertEquals('value-1', $result1); + $this->assertEquals(1, $callCount); + + // Second call should return cached value without executing callback + $result2 = $this->smartCache->remember($key, 3600, $callback); + $this->assertEquals('value-1', $result2); + $this->assertEquals(1, $callCount); // Count shouldn't increase + } + + public function test_can_use_remember_forever_method() + { + $key = 'remember-forever-key'; + $expectedValue = 'forever-value'; + + $result = $this->smartCache->rememberForever($key, function () use ($expectedValue) { + return $expectedValue; + }); + + $this->assertEquals($expectedValue, $result); + $this->assertEquals($expectedValue, $this->smartCache->get($key)); + } + + public function test_can_store_value_forever() + { + $key = 'forever-key'; + $value = 'forever-value'; + + $this->assertTrue($this->smartCache->forever($key, $value)); + $this->assertEquals($value, $this->smartCache->get($key)); + } + + public function test_can_forget_value() + { + $key = 'forget-key'; + $value = 'forget-value'; + + $this->smartCache->put($key, $value); + $this->assertTrue($this->smartCache->has($key)); + + $this->assertTrue($this->smartCache->forget($key)); + $this->assertFalse($this->smartCache->has($key)); + $this->assertNull($this->smartCache->get($key)); + } + + public function test_compression_strategy_is_applied_to_large_string() + { + // Create a fresh SmartCache instance with only compression strategy + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [new CompressionStrategy(1024, 6)] // 1KB threshold, level 6 + ); + + $key = 'large-string-key'; + $value = $this->createCompressibleData(); // Creates string > 1KB + + $smartCache->put($key, $value); + + // Get the raw cached value to check if it's compressed + $cached = $this->getCacheStore()->get($key); + $this->assertValueIsCompressed($cached); + + // Verify we can still retrieve the original value + $retrieved = $smartCache->get($key); + $this->assertEquals($value, $retrieved); + } + + public function test_compression_strategy_is_applied_to_large_array() + { + // Create a fresh SmartCache instance with only compression strategy + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [new CompressionStrategy(1024, 6)] // 1KB threshold, level 6 + ); + + $key = 'large-array-key'; + $value = $this->createLargeTestData(50); // Creates array that should exceed threshold + + $smartCache->put($key, $value); + + // Get the raw cached value to check if it's compressed + $cached = $this->getCacheStore()->get($key); + $this->assertValueIsCompressed($cached); + + // Verify we can still retrieve the original value + $retrieved = $smartCache->get($key); + $this->assertEquals($value, $retrieved); + } + + public function test_chunking_strategy_is_applied_to_very_large_array() + { + // Disable compression for this test to ensure chunking is applied + $this->app['config']->set('smart-cache.strategies.compression.enabled', false); + + // Create a fresh SmartCache instance with the new configuration + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [new ChunkingStrategy(2048, 100)] + ); + + $key = 'chunked-array-key'; + $value = $this->createChunkableData(); // Creates array that should trigger chunking + + $smartCache->put($key, $value); + + // Get the raw cached value to check if it's chunked + $cached = $this->getCacheStore()->get($key); + $this->assertValueIsChunked($cached); + + // Verify we can still retrieve the original value + $retrieved = $smartCache->get($key); + $this->assertEquals($value, $retrieved); + } + + public function test_small_values_are_not_optimized() + { + $key = 'small-value-key'; + $value = 'small value'; + + $this->smartCache->put($key, $value); + + // Get the raw cached value - should not be optimized + $cached = $this->getCacheStore()->get($key); + $this->assertEquals($value, $cached); + } + + public function test_can_clear_all_managed_keys() + { + // Store multiple values that will be optimized (use large data) + $keys = ['key1', 'key2', 'key3']; + $largeValue = $this->createCompressibleData(); // Use compressible data to ensure optimization + + foreach ($keys as $key) { + $this->smartCache->put($key, $largeValue); + } + + // Verify all are stored + foreach ($keys as $key) { + $this->assertTrue($this->smartCache->has($key)); + } + + // Clear all + $this->assertTrue($this->smartCache->clear()); + + // Verify all are removed + foreach ($keys as $key) { + $this->assertFalse($this->smartCache->has($key)); + } + } + + public function test_managed_keys_tracking() + { + $key1 = 'tracked-key-1'; + $key2 = 'tracked-key-2'; + + // Store a large value that triggers optimization + $largeValue = $this->createCompressibleData(); + $this->smartCache->put($key1, $largeValue); + + // Store a small value that doesn't trigger optimization + $this->smartCache->put($key2, 'small value'); + + $managedKeys = $this->smartCache->getManagedKeys(); + + // Only the optimized key should be tracked + $this->assertContains($key1, $managedKeys); + $this->assertNotContains($key2, $managedKeys); + } + + public function test_can_get_different_cache_stores() + { + // Test getting default store + $defaultStore = $this->smartCache->store(); + $this->assertEquals($this->getCacheStore(), $defaultStore); + + // Test getting named store + $arrayStore = $this->smartCache->store('array'); + $this->assertNotNull($arrayStore); + } + + public function test_chunked_data_cleanup_on_forget() + { + // Disable compression for this test to ensure chunking is applied + $this->app['config']->set('smart-cache.strategies.compression.enabled', false); + + // Create a fresh SmartCache instance with the new configuration + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [new ChunkingStrategy(2048, 100)] + ); + + $key = 'chunked-cleanup-key'; + $value = $this->createChunkableData(); + + $smartCache->put($key, $value); + + // Get the chunked metadata + $cached = $this->getCacheStore()->get($key); + $this->assertValueIsChunked($cached); + + // Verify chunk keys exist + foreach ($cached['chunk_keys'] as $chunkKey) { + $this->assertTrue($this->getCacheStore()->has($chunkKey)); + } + + // Forget the main key + $smartCache->forget($key); + + // Verify main key and all chunk keys are removed + $this->assertFalse($smartCache->has($key)); + foreach ($cached['chunk_keys'] as $chunkKey) { + $this->assertFalse($this->getCacheStore()->has($chunkKey)); + } + } + + public function test_optimization_fallback_on_strategy_failure() + { + // Create a SmartCache instance with a failing strategy + $failingStrategy = Mockery::mock(OptimizationStrategy::class); + $failingStrategy->shouldReceive('getIdentifier')->andReturn('failing'); + $failingStrategy->shouldReceive('shouldApply')->andReturn(true); + $failingStrategy->shouldReceive('optimize')->andThrow(new \Exception('Strategy failed')); + + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [$failingStrategy] + ); + + $key = 'fallback-key'; + $value = 'test value'; + + // Should not throw exception due to fallback + $this->assertTrue($smartCache->put($key, $value)); + $this->assertEquals($value, $smartCache->get($key)); + } + + public function test_restoration_fallback_on_strategy_failure() + { + // First store a value normally + $key = 'restoration-fallback-key'; + $value = 'test value'; + $this->smartCache->put($key, $value); + + // Create a SmartCache instance with a failing restoration strategy + $failingStrategy = Mockery::mock(OptimizationStrategy::class); + $failingStrategy->shouldReceive('getIdentifier')->andReturn('failing'); + $failingStrategy->shouldReceive('restore')->andThrow(new \Exception('Restoration failed')); + + $smartCache = new SmartCache( + $this->getCacheStore(), + $this->getCacheManager(), + $this->app['config'], + [$failingStrategy] + ); + + // Should return the original cached value as fallback + $retrieved = $smartCache->get($key); + $this->assertEquals($value, $retrieved); + } + + protected function tearDown(): void + { + Mockery::close(); + parent::tearDown(); + } +} diff --git a/tests/Unit/Strategies/ChunkingStrategyTest.php b/tests/Unit/Strategies/ChunkingStrategyTest.php new file mode 100644 index 0000000..b7ac267 --- /dev/null +++ b/tests/Unit/Strategies/ChunkingStrategyTest.php @@ -0,0 +1,312 @@ +strategy = new ChunkingStrategy(2048, 100); // 2KB threshold, 100 items per chunk + $this->mockCache = Mockery::mock(Repository::class); + } + + public function test_get_identifier_returns_chunking() + { + $this->assertEquals('chunking', $this->strategy->getIdentifier()); + } + + public function test_should_apply_returns_true_for_large_array() + { + $largeArray = $this->createLargeTestData(150); // 150 items, should exceed both size and count thresholds + $this->assertTrue($this->strategy->shouldApply($largeArray)); + } + + public function test_should_apply_returns_false_for_small_array() + { + $smallArray = range(1, 50); // Small array + $this->assertFalse($this->strategy->shouldApply($smallArray)); + } + + public function test_should_apply_returns_false_for_non_array_types() + { + $this->assertFalse($this->strategy->shouldApply('string')); + $this->assertFalse($this->strategy->shouldApply(123)); + $this->assertFalse($this->strategy->shouldApply(true)); + $this->assertFalse($this->strategy->shouldApply((object) ['key' => 'value'])); + } + + public function test_should_apply_respects_driver_configuration() + { + $largeArray = $this->createLargeTestData(150); + + $context = [ + 'driver' => 'redis', + 'config' => [ + 'drivers' => [ + 'redis' => [ + 'chunking' => false + ] + ] + ] + ]; + + $this->assertFalse($this->strategy->shouldApply($largeArray, $context)); + } + + public function test_should_apply_returns_false_if_array_count_below_chunk_size() + { + // Create array that's large in bytes but small in count + $largeItemArray = []; + for ($i = 0; $i < 50; $i++) { // Only 50 items (below chunk size of 100) + $largeItemArray[$i] = str_repeat('large content ', 100); // Each item is large + } + + // Should return false because count is below chunk size threshold + $this->assertFalse($this->strategy->shouldApply($largeItemArray)); + } + + public function test_optimize_creates_chunks() + { + $largeArray = range(1, 250); // 250 items + + // Setup mock cache expectations + $this->mockCache->shouldReceive('put')->times(3); // 250 items / 100 per chunk = 3 chunks + + $context = [ + 'cache' => $this->mockCache, + 'key' => 'test-key', + 'ttl' => 3600, + 'driver' => 'array' + ]; + + $optimized = $this->strategy->optimize($largeArray, $context); + + $this->assertIsArray($optimized); + $this->assertArrayHasKey('_sc_chunked', $optimized); + $this->assertTrue($optimized['_sc_chunked']); + $this->assertArrayHasKey('chunk_keys', $optimized); + $this->assertArrayHasKey('total_items', $optimized); + $this->assertArrayHasKey('is_collection', $optimized); + $this->assertArrayHasKey('original_key', $optimized); + + $this->assertEquals(250, $optimized['total_items']); + $this->assertFalse($optimized['is_collection']); + $this->assertCount(3, $optimized['chunk_keys']); // 3 chunks + } + + public function test_optimize_handles_collection_types() + { + // Skip if Collection class doesn't exist (in case illuminate/collections isn't available) + if (!class_exists('\Illuminate\Support\Collection')) { + $this->markTestSkipped('Illuminate\Support\Collection not available'); + } + + $collection = collect(range(1, 150)); + + $this->mockCache->shouldReceive('put')->times(2); // 150 items / 100 per chunk = 2 chunks + + $context = [ + 'cache' => $this->mockCache, + 'key' => 'collection-key', + 'ttl' => 3600 + ]; + + $optimized = $this->strategy->optimize($collection, $context); + + $this->assertTrue($optimized['is_collection']); + $this->assertCount(2, $optimized['chunk_keys']); + } + + public function test_optimize_without_cache_in_context() + { + $largeArray = range(1, 150); + + $context = [ + 'key' => 'test-key', + 'ttl' => 3600 + ]; + + $optimized = $this->strategy->optimize($largeArray, $context); + + // Should still create the metadata structure even without cache + $this->assertArrayHasKey('_sc_chunked', $optimized); + $this->assertTrue($optimized['_sc_chunked']); + $this->assertArrayHasKey('chunk_keys', $optimized); + } + + public function test_restore_reconstructs_original_array() + { + $originalArray = range(1, 250); + + // Create mock chunk data + $chunk1 = array_slice($originalArray, 0, 100, true); + $chunk2 = array_slice($originalArray, 100, 100, true); + $chunk3 = array_slice($originalArray, 200, 50, true); + + $chunkedMetadata = [ + '_sc_chunked' => true, + 'chunk_keys' => ['chunk_1', 'chunk_2', 'chunk_3'], + 'total_items' => 250, + 'is_collection' => false + ]; + + // Setup mock cache to return chunks + $this->mockCache->shouldReceive('get') + ->with('chunk_1')->andReturn($chunk1) + ->shouldReceive('get') + ->with('chunk_2')->andReturn($chunk2) + ->shouldReceive('get') + ->with('chunk_3')->andReturn($chunk3); + + $context = ['cache' => $this->mockCache]; + + $restored = $this->strategy->restore($chunkedMetadata, $context); + + $this->assertEquals($originalArray, $restored); + } + + public function test_restore_returns_collection_when_original_was_collection() + { + if (!class_exists('\Illuminate\Support\Collection')) { + $this->markTestSkipped('Illuminate\Support\Collection not available'); + } + + $originalArray = range(1, 150); + $chunk1 = array_slice($originalArray, 0, 100, true); + $chunk2 = array_slice($originalArray, 100, 50, true); + + $chunkedMetadata = [ + '_sc_chunked' => true, + 'chunk_keys' => ['chunk_1', 'chunk_2'], + 'total_items' => 150, + 'is_collection' => true + ]; + + $this->mockCache->shouldReceive('get') + ->with('chunk_1')->andReturn($chunk1) + ->shouldReceive('get') + ->with('chunk_2')->andReturn($chunk2); + + $context = ['cache' => $this->mockCache]; + + $restored = $this->strategy->restore($chunkedMetadata, $context); + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $restored); + $this->assertEquals($originalArray, $restored->all()); + } + + public function test_restore_returns_null_when_chunk_missing() + { + $chunkedMetadata = [ + '_sc_chunked' => true, + 'chunk_keys' => ['chunk_1', 'chunk_2'], + 'total_items' => 150, + 'is_collection' => false + ]; + + // Second chunk returns null (cache miss) + $this->mockCache->shouldReceive('get') + ->with('chunk_1')->andReturn(['some' => 'data']) + ->shouldReceive('get') + ->with('chunk_2')->andReturn(null); + + $context = ['cache' => $this->mockCache]; + + $restored = $this->strategy->restore($chunkedMetadata, $context); + + $this->assertNull($restored); + } + + public function test_restore_throws_exception_without_cache() + { + $chunkedMetadata = [ + '_sc_chunked' => true, + 'chunk_keys' => ['chunk_1'], + 'total_items' => 100, + 'is_collection' => false + ]; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cache repository is required to restore chunked data'); + + $this->strategy->restore($chunkedMetadata, []); // No cache in context + } + + public function test_restore_returns_unmodified_value_if_not_chunked() + { + $normalValue = ['not' => 'chunked']; + $restored = $this->strategy->restore($normalValue, ['cache' => $this->mockCache]); + $this->assertEquals($normalValue, $restored); + } + + public function test_chunking_with_custom_chunk_size() + { + $strategy = new ChunkingStrategy(2048, 50); // 50 items per chunk + $largeArray = range(1, 125); // 125 items + + $this->mockCache->shouldReceive('put')->times(3); // 125 / 50 = 3 chunks + + $context = [ + 'cache' => $this->mockCache, + 'key' => 'custom-chunk-key', + 'ttl' => 3600 + ]; + + $optimized = $strategy->optimize($largeArray, $context); + + $this->assertCount(3, $optimized['chunk_keys']); + } + + public function test_chunking_preserves_array_keys() + { + $originalArray = [ + 'first' => 'value1', + 'second' => 'value2', + 'third' => 'value3' + ]; + + // Add more items to exceed threshold + for ($i = 0; $i < 200; $i++) { + $originalArray["item_$i"] = "value_$i"; + } + + $this->mockCache->shouldReceive('put')->atLeast(1); + + // Also setup mock returns for restoration test + $chunks = array_chunk($originalArray, 100, true); + foreach ($chunks as $index => $chunk) { + $this->mockCache->shouldReceive('get') + ->with("_sc_chunk_test-key_$index") + ->andReturn($chunk); + } + + $context = [ + 'cache' => $this->mockCache, + 'key' => 'test-key', + 'ttl' => 3600 + ]; + + $optimized = $this->strategy->optimize($originalArray, $context); + $restored = $this->strategy->restore($optimized, $context); + + $this->assertEquals($originalArray, $restored); + $this->assertArrayHasKey('first', $restored); + $this->assertArrayHasKey('second', $restored); + $this->assertArrayHasKey('third', $restored); + } + + protected function tearDown(): void + { + Mockery::close(); + parent::tearDown(); + } +} diff --git a/tests/Unit/Strategies/CompressionStrategyTest.php b/tests/Unit/Strategies/CompressionStrategyTest.php new file mode 100644 index 0000000..22287ec --- /dev/null +++ b/tests/Unit/Strategies/CompressionStrategyTest.php @@ -0,0 +1,236 @@ +strategy = new CompressionStrategy(1024, 6); // 1KB threshold, level 6 + } + + public function test_get_identifier_returns_compression() + { + $this->assertEquals('compression', $this->strategy->getIdentifier()); + } + + public function test_should_apply_returns_true_for_large_string() + { + $largeString = str_repeat('a', 2000); // 2KB string + $this->assertTrue($this->strategy->shouldApply($largeString)); + } + + public function test_should_apply_returns_false_for_small_string() + { + $smallString = str_repeat('a', 500); // 500 bytes string + $this->assertFalse($this->strategy->shouldApply($smallString)); + } + + public function test_should_apply_returns_true_for_large_array() + { + $largeArray = $this->createLargeTestData(50); // Creates large array + $this->assertTrue($this->strategy->shouldApply($largeArray)); + } + + public function test_should_apply_returns_false_for_small_array() + { + $smallArray = ['key' => 'value']; + $this->assertFalse($this->strategy->shouldApply($smallArray)); + } + + public function test_should_apply_returns_true_for_large_object() + { + $largeObject = (object) $this->createLargeTestData(50); + $this->assertTrue($this->strategy->shouldApply($largeObject)); + } + + public function test_should_apply_returns_false_for_non_compressible_types() + { + $this->assertFalse($this->strategy->shouldApply(123)); + $this->assertFalse($this->strategy->shouldApply(123.45)); + $this->assertFalse($this->strategy->shouldApply(true)); + $this->assertFalse($this->strategy->shouldApply(null)); + } + + public function test_should_apply_respects_driver_configuration() + { + $largeString = str_repeat('a', 2000); + + $context = [ + 'driver' => 'redis', + 'config' => [ + 'drivers' => [ + 'redis' => [ + 'compression' => false + ] + ] + ] + ]; + + $this->assertFalse($this->strategy->shouldApply($largeString, $context)); + } + + public function test_optimize_compresses_string_data() + { + $originalString = str_repeat('Hello World! ', 200); // Repetitive string compresses well + $optimized = $this->strategy->optimize($originalString); + + $this->assertIsArray($optimized); + $this->assertArrayHasKey('_sc_compressed', $optimized); + $this->assertTrue($optimized['_sc_compressed']); + $this->assertArrayHasKey('data', $optimized); + $this->assertArrayHasKey('is_string', $optimized); + $this->assertTrue($optimized['is_string']); + + // Verify the compressed data is base64 encoded + $this->assertNotFalse(base64_decode($optimized['data'], true)); + } + + public function test_optimize_compresses_array_data() + { + $originalArray = $this->createLargeTestData(50); + $optimized = $this->strategy->optimize($originalArray); + + $this->assertIsArray($optimized); + $this->assertArrayHasKey('_sc_compressed', $optimized); + $this->assertTrue($optimized['_sc_compressed']); + $this->assertArrayHasKey('data', $optimized); + $this->assertArrayHasKey('is_string', $optimized); + $this->assertFalse($optimized['is_string']); + } + + public function test_optimize_compresses_object_data() + { + $originalObject = (object) $this->createLargeTestData(50); + $optimized = $this->strategy->optimize($originalObject); + + $this->assertIsArray($optimized); + $this->assertArrayHasKey('_sc_compressed', $optimized); + $this->assertTrue($optimized['_sc_compressed']); + $this->assertArrayHasKey('is_string', $optimized); + $this->assertFalse($optimized['is_string']); + } + + public function test_restore_returns_original_string() + { + $originalString = str_repeat('Hello World! ', 200); + $optimized = $this->strategy->optimize($originalString); + $restored = $this->strategy->restore($optimized); + + $this->assertEquals($originalString, $restored); + } + + public function test_restore_returns_original_array() + { + $originalArray = $this->createLargeTestData(50); + $optimized = $this->strategy->optimize($originalArray); + $restored = $this->strategy->restore($optimized); + + $this->assertEquals($originalArray, $restored); + } + + public function test_restore_returns_original_object() + { + $originalObject = (object) $this->createLargeTestData(50); + $optimized = $this->strategy->optimize($originalObject); + $restored = $this->strategy->restore($optimized); + + $this->assertEquals($originalObject, $restored); + } + + public function test_restore_returns_unmodified_value_if_not_compressed() + { + $normalValue = 'not compressed'; + $restored = $this->strategy->restore($normalValue); + $this->assertEquals($normalValue, $restored); + + $normalArray = ['not' => 'compressed']; + $restored = $this->strategy->restore($normalArray); + $this->assertEquals($normalArray, $restored); + } + + public function test_restore_returns_unmodified_value_if_invalid_compressed_format() + { + $invalidCompressed = [ + '_sc_compressed' => false, // Wrong marker + 'data' => 'some-data', + 'is_string' => true + ]; + + $restored = $this->strategy->restore($invalidCompressed); + $this->assertEquals($invalidCompressed, $restored); + } + + public function test_compression_reduces_size() + { + $repetitiveString = str_repeat('This is a test string that should compress very well. ', 100); + $originalSize = strlen($repetitiveString); + + $optimized = $this->strategy->optimize($repetitiveString); + $compressedSize = strlen($optimized['data']); + + // Base64 adds some overhead, but the compressed data should still be significantly smaller + // than the original for repetitive data + $this->assertLessThan($originalSize, $compressedSize); + } + + public function test_compression_with_different_levels() + { + $data = str_repeat('Test data for compression level testing. ', 100); + + $strategy1 = new CompressionStrategy(1024, 1); // Low compression + $strategy9 = new CompressionStrategy(1024, 9); // High compression + + $optimized1 = $strategy1->optimize($data); + $optimized9 = $strategy9->optimize($data); + + // Higher compression level should produce smaller result + $size1 = strlen($optimized1['data']); + $size9 = strlen($optimized9['data']); + + $this->assertLessThanOrEqual($size1, $size9); + + // Both should restore to the same original data + $restored1 = $strategy1->restore($optimized1); + $restored9 = $strategy9->restore($optimized9); + + $this->assertEquals($data, $restored1); + $this->assertEquals($data, $restored9); + } + + public function test_compression_with_custom_threshold() + { + $strategy = new CompressionStrategy(5000, 6); // 5KB threshold + + $smallData = str_repeat('a', 2000); // 2KB + $largeData = str_repeat('a', 6000); // 6KB + + $this->assertFalse($strategy->shouldApply($smallData)); + $this->assertTrue($strategy->shouldApply($largeData)); + } + + public function test_round_trip_compression_preserves_data_integrity() + { + $testCases = [ + 'Simple string', + str_repeat('Repetitive content ', 100), + ['array' => 'data', 'nested' => ['deep' => 'value']], + $this->createLargeTestData(30), + (object) ['property' => 'value', 'nested' => (object) ['deep' => 'data']] + ]; + + foreach ($testCases as $testCase) { + $optimized = $this->strategy->optimize($testCase); + $restored = $this->strategy->restore($optimized); + + $this->assertEquals($testCase, $restored, + 'Round-trip compression should preserve data integrity for: ' . gettype($testCase)); + } + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..6da9a00 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,54 @@ +isDir() ? 'rmdir' : 'unlink'); + $todo($fileinfo->getRealPath()); + } + } +}