diff --git a/.github/ISSUE_TEMPLATE/.github/workflows/linter.yml b/.github/ISSUE_TEMPLATE/.github/workflows/linter.yml
deleted file mode 100644
index c2f8cb6..0000000
--- a/.github/ISSUE_TEMPLATE/.github/workflows/linter.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: "Linter"
-
-on: [pull_request]
-jobs:
- lint:
- name: Linter
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
- with:
- fetch-depth: 2
-
- - run: git checkout HEAD^2
-
- - name: Run Linter
- run: |
- docker run --rm -v $PWD:/app composer sh -c \
- "composer install --profile --ignore-platform-reqs && composer lint"
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..dba4dad
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,100 @@
+name: "CI"
+
+on:
+ pull_request:
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup PHP 8.3
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.3"
+ coverage: none
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: Run Analyze
+ run: composer analyze
+
+ refactor:
+ name: Refactor
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup PHP 8.3
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.3"
+ coverage: none
+
+ - name: Validate tools/rector/composer.json
+ run: composer validate --strict --working-dir=tools/rector
+
+ - name: Install Rector dependencies
+ run: composer install --prefer-dist --no-progress --working-dir=tools/rector
+
+ - name: Run Refactor Check
+ run: composer refactor:check
+
+ format:
+ name: Format
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup PHP 8.3
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.3"
+ coverage: none
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: Run Format
+ run: composer format:check
+
+ tests:
+ name: Tests
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php-versions: ["8.2", "8.3", "8.4"]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup PHP ${{ matrix.php-versions }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ coverage: none
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: Run Tests
+ run: composer test
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index 126ef74..0000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: "CodeQL"
-
-on: [pull_request]
-jobs:
- lint:
- name: CodeQL
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - name: Run CodeQL
- run: |
- docker run --rm -v $PWD:/app composer sh -c \
- "composer install --profile --ignore-platform-reqs && composer check"
-
\ No newline at end of file
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
deleted file mode 100644
index 864d317..0000000
--- a/.github/workflows/lint.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: "Linter"
-
-on: [pull_request]
-jobs:
- lint:
- name: Linter
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - name: Run Linter
- run: |
- docker run --rm -v $PWD:/app composer sh -c \
- "composer install --profile --ignore-platform-reqs && composer lint"
\ No newline at end of file
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 06837d1..0000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: "Tests"
-
-on: [pull_request]
-jobs:
- lint:
- name: Tests
- runs-on: ubuntu-latest
- strategy:
- matrix:
- php-versions: ['8.2', '8.3', 'nightly']
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - name: Setup PHP ${{ matrix.php-versions }}
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php-versions }}
-
- - name: Validate composer.json and composer.lock
- run: composer validate --strict
-
- - name: Install dependencies
- run: composer install --no-progress --no-suggest
-
- - name: Run Tests
- run: vendor/bin/phpunit --configuration phpunit.xml
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 002c90b..5f89131 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/vendor/
/.idea/
-*.cache
\ No newline at end of file
+*.cache
+/tools/rector/vendor/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3ab8893..b4d952d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,109 +1,99 @@
# Contributing
-We would ❤️ for you to contribute to Utopia HTTP and help make it better! We want contributing to this library to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, new docs as well as updates and tweaks, blog posts, workshops, and more.
+Thanks for contributing to Utopia DI.
-## How to Start?
+This repository contains a small PSR-11 compatible dependency injection container used across the Utopia libraries. Contributions should keep that scope intact: small surface area, predictable behavior, and strong test coverage.
-If you are worried or don’t know where to start, check out our next section explaining what kind of help we could use and where can you get involved. You can reach out with questions to [Eldad Fux (@eldadfux)](https://twitter.com/eldadfux) or [@appwrite_io](https://twitter.com/appwrite_io) on Twitter, and anyone from the [Appwrite team on Discord](https://discord.gg/GSeTUeA). You can also submit an issue, and a maintainer can guide you!
+## Code Of Conduct
-You can get an in-depth understanding of Utopia HTTP in our [Getting Started](docs/Getting-Starting-Guide.md) guide.
+Please read and follow the [Code of Conduct](CODE_OF_CONDUCT.md).
-## Code of Conduct
+## Before You Start
-Help us keep Utopia HTTP open and inclusive. Please read and follow our [Code of Conduct](/CODE_OF_CONDUCT.md).
+- For bug fixes, documentation updates, and small improvements, open a pull request directly.
+- For larger API changes or new features, open an issue first so maintainers can confirm the direction before implementation.
+- For security issues, do not open a public issue. Email `security@appwrite.io` instead.
-## Submit a Pull Request 🚀
+## Development Setup
-Branch naming convention is as following
+Utopia DI requires PHP 8.2 or later.
-`TYPE-ISSUE_ID-DESCRIPTION`
+1. Fork the repository and clone your fork.
+2. Create a branch from `main`.
+3. Install root dependencies:
-example:
-
-```
-doc-548-submit-a-pull-request-section-to-contribution-guide
+```bash
+composer install
```
-When `TYPE` can be:
-
-- **feat** - is a new feature
-- **doc** - documentation only changes
-- **cicd** - changes related to CI/CD system
-- **fix** - a bug fix
-- **refactor** - code change that neither fixes a bug nor adds a feature
-
-**All PRs must include a commit message with the changes description!**
-
-For the initial start, fork the project and use git clone command to download the repository to your computer. A standard procedure for working on an issue would be to:
+4. Install Rector dependencies if you plan to run refactoring checks:
-1. `git pull`, before creating a new branch, pull the changes from upstream. Your master needs to be up to date.
-
-```
-$ git pull
+```bash
+composer install -d tools/rector
```
-2. Create new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`
+## Branches And Commits
-```
-$ git checkout -b [name_of_your_new_branch]
-```
+Use a short, descriptive branch name. Examples:
-3. Work - commit - repeat ( be sure to be in your branch )
+- `fix/scope-cache-behavior`
+- `docs/readme-scope-example`
+- `chore/update-tooling`
-4. Push changes to GitHub
+Write commit messages that clearly describe the change. Keep each pull request focused on a single concern.
-```
-$ git push origin [name_of_your_new_branch]
-```
-
-5. Submit your changes for review
- If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button.
-6. Start a Pull Request
- Now submit the pull request and click on `Create pull request`.
-7. Get a code review approval/reject
-8. After approval, merge your PR
-9. GitHub will automatically delete the branch after the merge is done. (they can still be restored).
-
-### Testing
-
-- `docker-compose up -d`
-- `docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml`
-- `docker-compose exec web vendor/bin/psalm --show-info=true`
-
-## Introducing New Features
+## Local Checks
-We would 💖 you to contribute to Utopia HTTP, but we would also like to make sure this library is as great as possible and loyal to its vision and mission statement 🙏.
+Run the relevant checks before opening a pull request:
-For us to find the right balance, please open an issue explaining your ideas before introducing a new pull request.
-
-This will allow the community to have sufficient discussion about the new feature value and how it fits in the product roadmap and vision.
-
-This is also important for the repository owners to be able to give technical input and different emphasis regarding the feature design and architecture. Some bigger features might need to go through our [RFC process](https://github.com/appwrite/rfc).
+```bash
+composer test
+composer analyze
+composer format:check
+composer refactor:check
+```
-## Other Ways to Help
+If you want to apply the automated fixes first:
-Pull requests are great, but there are many other areas where you can help:
+```bash
+composer fix
+```
-### Blogging & Speaking
+Notes:
-Creating blog posts, giving talks, or developing tutorials about one of this library's many features are excellent ways to contribute and help our project grow.
+- `composer test` runs PHPUnit using [phpunit.xml](phpunit.xml).
+- `composer analyze` runs PHPStan using [phpstan.neon](phpstan.neon).
+- `composer format:check` runs Pint in check mode.
+- `composer refactor:check` requires `tools/rector` dependencies to be installed first.
-### Presenting at Meetups
+## Pull Requests
-Presenting at meetups and conferences about your Utopia projects. Your unique challenges and successes in building things with this library can provide great speaking material. We’d love to review your conference talk abstract, so get in touch with us if you’d like some help!
+When opening a pull request:
-### Sending Feedbacks & Reporting Bugs
+- Base it on `main`.
+- Explain the problem and the approach you took to solve it.
+- Link the related issue when there is one.
+- Add or update tests for behavior changes.
+- Update documentation when public behavior or examples change.
+- Avoid mixing unrelated refactors with functional changes.
-Sending feedback is a great way for us to understand your different use cases of this library better. If you had any issues, bugs, or want to share about your experience, feel free to do so on our GitHub issues page or at our [Discord channel](https://discord.gg/GSeTUeA).
+All changes should go through pull request review before merging.
-### Submitting New Ideas
+## What Maintainers Look For
-If you think this library could use a new feature, please open an issue on our GitHub repository, stating as much information as you can think about your new idea and it's implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.
+The strongest contributions usually have these properties:
-### Improving Documentation
+- The change matches the library's narrow scope.
+- The public API stays simple and consistent.
+- Edge cases are covered with tests.
+- Error messages stay clear and actionable.
+- Documentation reflects the final behavior.
-Submitting documentation updates, enhancements, designs, or bug fixes. Spelling or grammar fixes will be very much appreciated.
+## Other Ways To Help
-### Helping Someone
+You can also contribute by:
-Searching for Utopia HTTP on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to this repo!
+- reporting bugs and inconsistencies
+- improving examples and documentation
+- reviewing pull requests
+- helping other users in issues and community channels
diff --git a/README.md b/README.md
index ef48f2e..0b1aad3 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,11 @@
-[](https://travis-ci.org/utopia-php/http)
-
+[](https://github.com/utopia-php/di/actions/workflows/ci.yml)
+
[](https://discord.gg/GSeTUeA)
-Utopia DI library is simple and lite library for managing dependency injections. This library is aiming to be as simple and easy to learn and use. This library is maintained by the [Appwrite team](https://appwrite.io).
+Utopia DI is a small PSR-11 compatible dependency injection container with parent-child scopes. It is designed to stay simple while still covering the dependency lifecycle used across the Utopia libraries. This library is maintained by the [Appwrite team](https://appwrite.io).
Although this library is part of the Utopia Framework project it is dependency free, and can be used as standalone with any other PHP project or framework.
@@ -15,25 +15,100 @@ Although this library is part of the Utopia Framework project it is dependency f
Install using Composer:
```bash
-composer require utopia-php/http
+composer require utopia-php/di
```
-
```php
require_once __DIR__.'/../vendor/autoload.php';
+use Psr\Container\ContainerInterface;
use Utopia\DI\Container;
+use Utopia\DI\Dependency;
+
+$di = new Container();
+
+$di->set(
+ key: 'age',
+ factory: new Dependency(
+ injections: [],
+ callback: fn () => 25
+ )
+);
+
+$di->set(
+ key: 'john',
+ factory: new Dependency(
+ injections: ['age'],
+ callback: fn (int $age) => 'John Doe is '.$age.' years old.'
+ )
+);
+
+$john = $di->get('john');
+```
+
+For `Dependency` factories, the `injections` array is matched to callback parameter names, so the array order does not need to mirror the callback signature.
+
+You can still register plain factories directly when you want access to the container instance.
+
+```php
+$di->set(
+ key: 'config',
+ factory: fn (ContainerInterface $container) => [
+ 'dsn' => 'mysql:host=localhost;dbname=app',
+ 'username' => 'root',
+ 'password' => 'secret',
+ ]
+);
+
+$request = $di->scope();
+
+$request->set(
+ key: 'db',
+ factory: fn (ContainerInterface $container) => new PDO(
+ $container->get('config')['dsn'],
+ $container->get('config')['username'],
+ $container->get('config')['password']
+ )
+);
+```
+
+Factories are resolved once per container instance. A child scope behaves in two distinct ways:
+
+- If the child does not define a key, it falls back to the parent and reuses the parent's resolved value.
+- If the child defines the same key locally, it resolves and caches its own value without changing the parent.
+
+```php
+$counter = 0;
+
+$di->set('requestId', function () use (&$counter): string {
+ $counter++;
+
+ return 'request-'.$counter;
+});
+
+$di->get('requestId'); // "request-1"
+
+$child = $di->scope();
+
+$child->get('requestId'); // "request-1" (falls back to the parent cache)
+
+$child->set('requestId', function () use (&$counter): string {
+ $counter++;
+
+ return 'request-'.$counter;
+});
-TBD
+$child->get('requestId'); // "request-2" (child now uses its own local definition)
+$di->get('requestId'); // "request-1" (parent is unchanged)
```
## System Requirements
-Utopia HTTP requires PHP 8.1 or later. We recommend using the latest PHP version whenever possible.
+Utopia DI requires PHP 8.2 or later. We recommend using the latest PHP version whenever possible.
## More from Utopia
-Our ecosystem supports other thin PHP projects aiming to extend the core PHP Utopia HTTP.
+Our ecosystem supports other thin PHP projects aiming to extend the core PHP Utopia libraries.
Each project is focused on solving a single, very simple problem and you can use composer to include any of them in your next project.
@@ -45,7 +120,7 @@ All code contributions - including those of people having commit access - must g
Fork the project, create a feature branch, and send us a pull request.
-You can refer to the [Contributing Guide](https://github.com/utopia-php/http/blob/master/CONTRIBUTING.md) for more info.
+You can refer to the [Contributing Guide](https://github.com/utopia-php/di/blob/master/CONTRIBUTING.md) for more info.
For security issues, please email security@appwrite.io instead of posting a public issue in GitHub.
diff --git a/composer.json b/composer.json
index 7c412d3..8d1730a 100644
--- a/composer.json
+++ b/composer.json
@@ -4,31 +4,46 @@
"type": "library",
"keywords": [
"php",
- "framework",
- "http",
- "upf"
+ "di",
+ "dependency-injection",
+ "container",
+ "psr-11",
+ "utopia"
],
"license": "MIT",
+ "require": {
+ "php": ">=8.2",
+ "psr/container": "^2.0"
+ },
+ "require-dev": {
+ "laravel/pint": "^1.27",
+ "phpbench/phpbench": "^1.2",
+ "phpstan/phpstan": "^2.1",
+ "phpunit/phpunit": "^9.5.25",
+ "swoole/ide-helper": "4.8.3"
+ },
"autoload": {
"psr-4": {
"Utopia\\": "src/",
"Tests\\E2E\\": "tests/e2e"
}
},
+ "config": {
+ "platform": {
+ "php": "8.2"
+ }
+ },
"scripts": {
- "lint": "vendor/bin/pint --test",
"format": "vendor/bin/pint",
- "check": "vendor/bin/phpstan analyse -c phpstan.neon",
+ "format:check": "vendor/bin/pint --test",
+ "analyze": "vendor/bin/phpstan analyse --memory-limit=512M",
+ "refactor": "tools/rector/vendor/bin/rector process --config=rector.php",
+ "refactor:check": "tools/rector/vendor/bin/rector process --dry-run --config=rector.php",
+ "fix": [
+ "@refactor",
+ "@analyze",
+ "@format"
+ ],
"test": "vendor/bin/phpunit --configuration phpunit.xml"
- },
- "require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.5.25",
- "laravel/pint": "^1.2",
- "swoole/ide-helper": "4.8.3",
- "phpstan/phpstan": "^1.10",
- "phpbench/phpbench": "^1.2"
}
}
diff --git a/composer.lock b/composer.lock
index d5c5fc5..d5e2367 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,21 +4,75 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a9214c1b1e10d26dde2c89b8b0718584",
- "packages": [],
+ "content-hash": "5704a5eda191e5bbb8a67d91b7ec9b4f",
+ "packages": [
+ {
+ "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"
+ }
+ ],
"packages-dev": [
{
"name": "doctrine/annotations",
- "version": "2.0.1",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
- "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f"
+ "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
- "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7",
+ "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7",
"shasum": ""
},
"require": {
@@ -30,10 +84,10 @@
"require-dev": {
"doctrine/cache": "^2.0",
"doctrine/coding-standard": "^10",
- "phpstan/phpstan": "^1.8.0",
+ "phpstan/phpstan": "^1.10.28",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "symfony/cache": "^5.4 || ^6",
- "vimeo/psalm": "^4.10"
+ "symfony/cache": "^5.4 || ^6.4 || ^7",
+ "vimeo/psalm": "^4.30 || ^5.14"
},
"suggest": {
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
@@ -79,9 +133,10 @@
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
- "source": "https://github.com/doctrine/annotations/tree/2.0.1"
+ "source": "https://github.com/doctrine/annotations/tree/2.0.2"
},
- "time": "2023-02-02T22:02:53+00:00"
+ "abandoned": true,
+ "time": "2024-09-05T10:17:24+00:00"
},
{
"name": "doctrine/instantiator",
@@ -232,16 +287,16 @@
},
{
"name": "laravel/pint",
- "version": "v1.15.1",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "5f288b5e79938cc72f5c298d384e639de87507c6"
+ "reference": "1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/5f288b5e79938cc72f5c298d384e639de87507c6",
- "reference": "5f288b5e79938cc72f5c298d384e639de87507c6",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9",
+ "reference": "1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9",
"shasum": ""
},
"require": {
@@ -249,16 +304,17 @@
"ext-mbstring": "*",
"ext-tokenizer": "*",
"ext-xml": "*",
- "php": "^8.1.0"
+ "php": "^8.2.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.52.1",
- "illuminate/view": "^10.48.4",
- "larastan/larastan": "^2.9.2",
- "laravel-zero/framework": "^10.3.0",
- "mockery/mockery": "^1.6.11",
- "nunomaduro/termwind": "^1.15.1",
- "pestphp/pest": "^2.34.5"
+ "friendsofphp/php-cs-fixer": "^3.94.2",
+ "illuminate/view": "^12.54.1",
+ "larastan/larastan": "^3.9.3",
+ "laravel-zero/framework": "^12.0.5",
+ "mockery/mockery": "^1.6.12",
+ "nunomaduro/termwind": "^2.4.0",
+ "pestphp/pest": "^3.8.5",
+ "shipfastlabs/agent-detector": "^1.0.2"
},
"bin": [
"builds/pint"
@@ -284,6 +340,7 @@
"description": "An opinionated code formatter for PHP.",
"homepage": "https://laravel.com",
"keywords": [
+ "dev",
"format",
"formatter",
"lint",
@@ -294,20 +351,20 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2024-04-02T14:28:47+00:00"
+ "time": "2026-03-10T20:37:18+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.11.1",
+ "version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
- "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
@@ -315,11 +372,12 @@
},
"conflict": {
"doctrine/collections": "<1.6.8",
- "doctrine/common": "<2.13.3 || >=3,<3.2.2"
+ "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",
@@ -345,7 +403,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
},
"funding": [
{
@@ -353,20 +411,20 @@
"type": "tidelift"
}
],
- "time": "2023-03-08T13:26:56+00:00"
+ "time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.0.2",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
- "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -377,7 +435,7 @@
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
- "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+ "phpunit/phpunit": "^9.0"
},
"bin": [
"bin/php-parse"
@@ -385,7 +443,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-master": "5.x-dev"
}
},
"autoload": {
@@ -409,9 +467,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
},
- "time": "2024-03-05T20:51:40+00:00"
+ "time": "2025-12-06T11:56:16+00:00"
},
{
"name": "phar-io/manifest",
@@ -533,24 +591,24 @@
},
{
"name": "phpbench/container",
- "version": "2.2.2",
+ "version": "2.2.3",
"source": {
"type": "git",
"url": "https://github.com/phpbench/container.git",
- "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33"
+ "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpbench/container/zipball/a59b929e00b87b532ca6d0edd8eca0967655af33",
- "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33",
+ "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196",
+ "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196",
"shasum": ""
},
"require": {
"psr/container": "^1.0|^2.0",
- "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0"
+ "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^2.16",
+ "php-cs-fixer/shim": "^3.89",
"phpstan/phpstan": "^0.12.52",
"phpunit/phpunit": "^8"
},
@@ -578,73 +636,22 @@
"description": "Simple, configurable, service container.",
"support": {
"issues": "https://github.com/phpbench/container/issues",
- "source": "https://github.com/phpbench/container/tree/2.2.2"
- },
- "time": "2023-10-30T13:38:26+00:00"
- },
- {
- "name": "phpbench/dom",
- "version": "0.3.3",
- "source": {
- "type": "git",
- "url": "https://github.com/phpbench/dom.git",
- "reference": "786a96db538d0def931f5b19225233ec42ec7a72"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpbench/dom/zipball/786a96db538d0def931f5b19225233ec42ec7a72",
- "reference": "786a96db538d0def931f5b19225233ec42ec7a72",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "php": "^7.3||^8.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^3.14",
- "phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^8.0||^9.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
+ "source": "https://github.com/phpbench/container/tree/2.2.3"
},
- "autoload": {
- "psr-4": {
- "PhpBench\\Dom\\": "lib/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Leech",
- "email": "daniel@dantleech.com"
- }
- ],
- "description": "DOM wrapper to simplify working with the PHP DOM implementation",
- "support": {
- "issues": "https://github.com/phpbench/dom/issues",
- "source": "https://github.com/phpbench/dom/tree/0.3.3"
- },
- "time": "2023-03-06T23:46:57+00:00"
+ "time": "2025-11-06T09:05:13+00:00"
},
{
"name": "phpbench/phpbench",
- "version": "1.2.15",
+ "version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpbench/phpbench.git",
- "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c"
+ "reference": "9a28fd0833f11171b949843c6fd663eb69b6d14c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpbench/phpbench/zipball/f7000319695cfad04a57fc64bf7ef7abdf4c437c",
- "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c",
+ "url": "https://api.github.com/repos/phpbench/phpbench/zipball/9a28fd0833f11171b949843c6fd663eb69b6d14c",
+ "reference": "9a28fd0833f11171b949843c6fd663eb69b6d14c",
"shasum": ""
},
"require": {
@@ -655,30 +662,31 @@
"ext-reflection": "*",
"ext-spl": "*",
"ext-tokenizer": "*",
- "php": "^8.1",
- "phpbench/container": "^2.1",
- "phpbench/dom": "~0.3.3",
+ "php": "^8.2",
+ "phpbench/container": "^2.2",
"psr/log": "^1.1 || ^2.0 || ^3.0",
"seld/jsonlint": "^1.1",
- "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0",
- "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0",
- "symfony/finder": "^4.2 || ^5.0 || ^6.0 || ^7.0",
- "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0",
- "symfony/process": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/console": "^6.1 || ^7.0 || ^8.0",
+ "symfony/filesystem": "^6.1 || ^7.0 || ^8.0",
+ "symfony/finder": "^6.1 || ^7.0 || ^8.0",
+ "symfony/options-resolver": "^6.1 || ^7.0 || ^8.0",
+ "symfony/process": "^6.1 || ^7.0 || ^8.0",
"webmozart/glob": "^4.6"
},
"require-dev": {
"dantleech/invoke": "^2.0",
- "friendsofphp/php-cs-fixer": "^3.0",
+ "ergebnis/composer-normalize": "^2.39",
"jangregor/phpstan-prophecy": "^1.0",
- "phpspec/prophecy": "dev-master",
+ "php-cs-fixer/shim": "^3.9",
+ "phpspec/prophecy": "^1.22",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
- "phpunit/phpunit": "^10.0",
- "rector/rector": "^0.18.10",
- "symfony/error-handler": "^5.2 || ^6.0 || ^7.0",
- "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ "phpunit/phpunit": "^11.5",
+ "rector/rector": "^1.2",
+ "sebastian/exporter": "^6.3.2",
+ "symfony/error-handler": "^6.1 || ^7.0 || ^8.0",
+ "symfony/var-dumper": "^6.1 || ^7.0 || ^8.0"
},
"suggest": {
"ext-xdebug": "For Xdebug profiling extension."
@@ -721,7 +729,7 @@
],
"support": {
"issues": "https://github.com/phpbench/phpbench/issues",
- "source": "https://github.com/phpbench/phpbench/tree/1.2.15"
+ "source": "https://github.com/phpbench/phpbench/tree/1.5.1"
},
"funding": [
{
@@ -729,24 +737,19 @@
"type": "github"
}
],
- "time": "2023-11-29T12:21:11+00:00"
+ "time": "2026-03-05T08:18:58+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.10.67",
- "source": {
- "type": "git",
- "url": "https://github.com/phpstan/phpstan.git",
- "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493"
- },
+ "version": "2.1.40",
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493",
- "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
+ "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
"shasum": ""
},
"require": {
- "php": "^7.2|^8.0"
+ "php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
@@ -787,39 +790,39 @@
"type": "github"
}
],
- "time": "2024-04-16T07:22:02+00:00"
+ "time": "2026-02-23T15:04:35+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.31",
+ "version": "9.2.32",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965"
+ "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965",
- "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5",
+ "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.18 || ^5.0",
+ "nikic/php-parser": "^4.19.1 || ^5.1.0",
"php": ">=7.3",
- "phpunit/php-file-iterator": "^3.0.3",
- "phpunit/php-text-template": "^2.0.2",
- "sebastian/code-unit-reverse-lookup": "^2.0.2",
- "sebastian/complexity": "^2.0",
- "sebastian/environment": "^5.1.2",
- "sebastian/lines-of-code": "^1.0.3",
- "sebastian/version": "^3.0.1",
- "theseer/tokenizer": "^1.2.0"
+ "phpunit/php-file-iterator": "^3.0.6",
+ "phpunit/php-text-template": "^2.0.4",
+ "sebastian/code-unit-reverse-lookup": "^2.0.3",
+ "sebastian/complexity": "^2.0.3",
+ "sebastian/environment": "^5.1.5",
+ "sebastian/lines-of-code": "^1.0.4",
+ "sebastian/version": "^3.0.2",
+ "theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^9.6"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -828,7 +831,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.2-dev"
+ "dev-main": "9.2.x-dev"
}
},
"autoload": {
@@ -857,7 +860,7 @@
"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/9.2.31"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32"
},
"funding": [
{
@@ -865,7 +868,7 @@
"type": "github"
}
],
- "time": "2024-03-02T06:37:42+00:00"
+ "time": "2024-08-22T04:23:01+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1110,45 +1113,45 @@
},
{
"name": "phpunit/phpunit",
- "version": "9.6.19",
+ "version": "9.6.34",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8"
+ "reference": "b36f02317466907a230d3aa1d34467041271ef4a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8",
- "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a",
+ "reference": "b36f02317466907a230d3aa1d34467041271ef4a",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.3.1 || ^2",
+ "doctrine/instantiator": "^1.5.0 || ^2",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.10.1",
- "phar-io/manifest": "^2.0.3",
- "phar-io/version": "^3.0.2",
+ "myclabs/deep-copy": "^1.13.4",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
"php": ">=7.3",
- "phpunit/php-code-coverage": "^9.2.28",
- "phpunit/php-file-iterator": "^3.0.5",
+ "phpunit/php-code-coverage": "^9.2.32",
+ "phpunit/php-file-iterator": "^3.0.6",
"phpunit/php-invoker": "^3.1.1",
- "phpunit/php-text-template": "^2.0.3",
- "phpunit/php-timer": "^5.0.2",
- "sebastian/cli-parser": "^1.0.1",
- "sebastian/code-unit": "^1.0.6",
- "sebastian/comparator": "^4.0.8",
- "sebastian/diff": "^4.0.3",
- "sebastian/environment": "^5.1.3",
- "sebastian/exporter": "^4.0.5",
- "sebastian/global-state": "^5.0.1",
- "sebastian/object-enumerator": "^4.0.3",
- "sebastian/resource-operations": "^3.0.3",
- "sebastian/type": "^3.2",
+ "phpunit/php-text-template": "^2.0.4",
+ "phpunit/php-timer": "^5.0.3",
+ "sebastian/cli-parser": "^1.0.2",
+ "sebastian/code-unit": "^1.0.8",
+ "sebastian/comparator": "^4.0.10",
+ "sebastian/diff": "^4.0.6",
+ "sebastian/environment": "^5.1.5",
+ "sebastian/exporter": "^4.0.8",
+ "sebastian/global-state": "^5.0.8",
+ "sebastian/object-enumerator": "^4.0.4",
+ "sebastian/resource-operations": "^3.0.4",
+ "sebastian/type": "^3.2.1",
"sebastian/version": "^3.0.2"
},
"suggest": {
@@ -1193,7 +1196,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34"
},
"funding": [
{
@@ -1204,12 +1207,20 @@
"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": "2024-04-05T04:35:58+00:00"
+ "time": "2026-01-27T05:45:00+00:00"
},
{
"name": "psr/cache",
@@ -1260,71 +1271,18 @@
},
"time": "2021-02-03T23:26:27+00:00"
},
- {
- "name": "psr/container",
- "version": "2.0.2",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/container.git",
- "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
- "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
- "shasum": ""
- },
- "require": {
- "php": ">=7.4.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Psr\\Container\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
- }
- ],
- "description": "Common Container Interface (PHP FIG PSR-11)",
- "homepage": "https://github.com/php-fig/container",
- "keywords": [
- "PSR-11",
- "container",
- "container-interface",
- "container-interop",
- "psr"
- ],
- "support": {
- "issues": "https://github.com/php-fig/container/issues",
- "source": "https://github.com/php-fig/container/tree/2.0.2"
- },
- "time": "2021-11-05T16:47:00+00:00"
- },
{
"name": "psr/log",
- "version": "3.0.0",
+ "version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"shasum": ""
},
"require": {
@@ -1359,9 +1317,9 @@
"psr-3"
],
"support": {
- "source": "https://github.com/php-fig/log/tree/3.0.0"
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
},
- "time": "2021-07-14T16:46:02+00:00"
+ "time": "2024-09-11T13:17:53+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -1532,16 +1490,16 @@
},
{
"name": "sebastian/comparator",
- "version": "4.0.8",
+ "version": "4.0.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
+ "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d",
+ "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d",
"shasum": ""
},
"require": {
@@ -1594,15 +1552,27 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
}
],
- "time": "2022-09-14T12:41:17+00:00"
+ "time": "2026-01-24T09:22:56+00:00"
},
{
"name": "sebastian/complexity",
@@ -1792,16 +1762,16 @@
},
{
"name": "sebastian/exporter",
- "version": "4.0.6",
+ "version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
+ "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
- "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c",
+ "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c",
"shasum": ""
},
"require": {
@@ -1857,28 +1827,40 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "type": "tidelift"
}
],
- "time": "2024-03-02T06:33:00+00:00"
+ "time": "2025-09-24T06:03:27+00:00"
},
{
"name": "sebastian/global-state",
- "version": "5.0.7",
+ "version": "5.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9"
+ "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
- "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6",
+ "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6",
"shasum": ""
},
"require": {
@@ -1921,15 +1903,27 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state",
+ "type": "tidelift"
}
],
- "time": "2024-03-02T06:35:11+00:00"
+ "time": "2025-08-10T07:10:35+00:00"
},
{
"name": "sebastian/lines-of-code",
@@ -2102,16 +2096,16 @@
},
{
"name": "sebastian/recursion-context",
- "version": "4.0.5",
+ "version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
+ "reference": "539c6691e0623af6dc6f9c20384c120f963465a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
- "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0",
+ "reference": "539c6691e0623af6dc6f9c20384c120f963465a0",
"shasum": ""
},
"require": {
@@ -2153,15 +2147,27 @@
"homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "type": "tidelift"
}
],
- "time": "2023-02-03T06:07:39+00:00"
+ "time": "2025-08-10T06:57:39+00:00"
},
{
"name": "sebastian/resource-operations",
@@ -2328,23 +2334,23 @@
},
{
"name": "seld/jsonlint",
- "version": "1.10.2",
+ "version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
- "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259"
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9bb7db07b5d66d90f6ebf542f09fc67d800e5259",
- "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
},
"bin": [
@@ -2376,7 +2382,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/jsonlint/issues",
- "source": "https://github.com/Seldaek/jsonlint/tree/1.10.2"
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0"
},
"funding": [
{
@@ -2388,7 +2394,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-07T12:57:50+00:00"
+ "time": "2024-07-11T14:55:45+00:00"
},
{
"name": "swoole/ide-helper",
@@ -2434,23 +2440,24 @@
},
{
"name": "symfony/console",
- "version": "v7.0.6",
+ "version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5"
+ "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
- "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
+ "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d",
+ "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^6.4|^7.0"
+ "symfony/string": "^7.2|^8.0"
},
"conflict": {
"symfony/dependency-injection": "<6.4",
@@ -2464,16 +2471,16 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/lock": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/lock": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2507,7 +2514,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.0.6"
+ "source": "https://github.com/symfony/console/tree/v7.4.7"
},
"funding": [
{
@@ -2518,25 +2525,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-04-01T11:04:53+00:00"
+ "time": "2026-03-06T14:06:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.4.0",
+ "version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
@@ -2544,12 +2555,12 @@
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.4-dev"
- },
"thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -2574,7 +2585,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@@ -2590,20 +2601,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-23T14:45:45+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v7.0.6",
+ "version": "v7.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "408105dff4c104454100730bdfd1a9cdd993f04d"
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d",
- "reference": "408105dff4c104454100730bdfd1a9cdd993f04d",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
"shasum": ""
},
"require": {
@@ -2611,6 +2622,9 @@
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
+ "require-dev": {
+ "symfony/process": "^6.4|^7.0|^8.0"
+ },
"type": "library",
"autoload": {
"psr-4": {
@@ -2637,7 +2651,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.0.6"
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.6"
},
"funding": [
{
@@ -2648,32 +2662,36 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-03-21T19:37:36+00:00"
+ "time": "2026-02-25T16:50:00+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.0.0",
+ "version": "v7.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56"
+ "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
- "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
+ "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
"require-dev": {
- "symfony/filesystem": "^6.4|^7.0"
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2701,7 +2719,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.0.0"
+ "source": "https://github.com/symfony/finder/tree/v7.4.6"
},
"funding": [
{
@@ -2712,25 +2730,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2023-10-31T17:59:56+00:00"
+ "time": "2026-01-29T09:40:50+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v7.0.0",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f"
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80",
"shasum": ""
},
"require": {
@@ -2768,7 +2790,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
},
"funding": [
{
@@ -2779,29 +2801,33 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2023-08-08T10:20:21+00:00"
+ "time": "2025-11-12T15:39:26+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.29.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
- "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
@@ -2812,8 +2838,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -2847,7 +2873,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
},
"funding": [
{
@@ -2858,29 +2884,33 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.29.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
@@ -2888,8 +2918,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -2925,7 +2955,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
},
"funding": [
{
@@ -2936,29 +2966,33 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2025-06-27T09:58:17+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.29.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
@@ -2966,8 +3000,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -3006,7 +3040,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
},
"funding": [
{
@@ -3017,29 +3051,34 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.29.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "ext-iconv": "*",
+ "php": ">=7.2"
},
"provide": {
"ext-mbstring": "*"
@@ -3050,8 +3089,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -3086,7 +3125,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
},
"funding": [
{
@@ -3097,25 +3136,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/process",
- "version": "v7.0.4",
+ "version": "v7.4.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
+ "reference": "608476f4604102976d687c483ac63a79ba18cc97"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
+ "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97",
+ "reference": "608476f4604102976d687c483ac63a79ba18cc97",
"shasum": ""
},
"require": {
@@ -3147,7 +3190,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.0.4"
+ "source": "https://github.com/symfony/process/tree/v7.4.5"
},
"funding": [
{
@@ -3158,42 +3201,47 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-02-22T20:27:20+00:00"
+ "time": "2026-01-26T15:07:59+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.4.2",
+ "version": "v3.6.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
- "reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
"shasum": ""
},
"require": {
"php": ">=8.1",
- "psr/container": "^1.1|^2.0"
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.4-dev"
- },
"thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -3229,7 +3277,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
},
"funding": [
{
@@ -3240,31 +3288,36 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2023-12-19T21:51:00+00:00"
+ "time": "2025-07-15T11:30:57+00:00"
},
{
"name": "symfony/string",
- "version": "v7.0.4",
+ "version": "v7.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b"
+ "reference": "9f209231affa85aa930a5e46e6eb03381424b30b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b",
- "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b",
+ "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b",
+ "reference": "9f209231affa85aa930a5e46e6eb03381424b30b",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3.0",
"symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-grapheme": "~1.33",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
@@ -3272,11 +3325,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
+ "symfony/emoji": "^7.1|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -3315,7 +3368,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.0.4"
+ "source": "https://github.com/symfony/string/tree/v7.4.6"
},
"funding": [
{
@@ -3326,25 +3379,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-02-01T13:17:36+00:00"
+ "time": "2026-02-09T09:33:46+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.2.3",
+ "version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
- "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
"shasum": ""
},
"require": {
@@ -3373,7 +3430,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
+ "source": "https://github.com/theseer/tokenizer/tree/1.3.1"
},
"funding": [
{
@@ -3381,7 +3438,7 @@
"type": "github"
}
],
- "time": "2024-03-03T12:36:25+00:00"
+ "time": "2025-11-17T20:03:58+00:00"
},
{
"name": "webmozart/glob",
@@ -3435,12 +3492,15 @@
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=8.2"
},
- "platform-dev": [],
+ "platform-dev": {},
+ "platform-overrides": {
+ "php": "8.2"
+ },
"plugin-api-version": "2.6.0"
}
diff --git a/phpstan.neon b/phpstan.neon
index d275a39..902da9b 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,7 +1,7 @@
parameters:
- scanDirectories:
- - vendor/swoole/ide-helper
level: 5
paths:
- src
- - tests
\ No newline at end of file
+ - tests
+ scanDirectories:
+ - vendor/swoole/ide-helper
diff --git a/rector.php b/rector.php
new file mode 100644
index 0000000..43f6cbf
--- /dev/null
+++ b/rector.php
@@ -0,0 +1,23 @@
+withPaths([
+ __DIR__ . '/src',
+ __DIR__ . '/tests',
+ ])
+ ->withSkip([
+ __DIR__ . '/vendor',
+ ThrowWithPreviousExceptionRector::class,
+ ])
+ ->withPhpSets(php82: true)
+ ->withPreparedSets(
+ deadCode: true,
+ codeQuality: true,
+ typeDeclarations: true,
+ phpunitCodeQuality: true,
+ );
diff --git a/src/DI/Container.php b/src/DI/Container.php
index fe4a607..3790c40 100644
--- a/src/DI/Container.php
+++ b/src/DI/Container.php
@@ -2,131 +2,107 @@
namespace Utopia\DI;
-use Exception;
-
-class Container
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use Utopia\DI\Exceptions\ContainerException;
+use Utopia\DI\Exceptions\NotFoundException;
+
+/**
+ * @phpstan-consistent-constructor
+ */
+class Container implements ContainerInterface
{
/**
- * @var array
+ * @var array
*/
- protected array $dependencies = [];
+ private array $definitions = [];
/**
- * @var array
+ * @var array
*/
- protected array $instances = [];
-
- public function __construct()
- {
- $di = new Dependency();
- $di->setName('di');
- $di->setCallback(function () {
- return $this;
- });
- $this->dependencies[$di->getName()] = $di;
- }
+ private array $resolved = [];
/**
- * Set a dependency.
- *
- * @param Dependency|Injection $dependency
- * @return self
- *
- * @throws Exception
+ * @var array
*/
- public function set(Dependency|Injection $dependency): self
- {
- if ($dependency->getName() === 'di') {
- throw new Exception("'di' is a reserved keyword.");
- }
+ private array $resolving = [];
- if (\array_key_exists($dependency->getName(), $this->instances)) {
- unset($this->instances[$dependency->getName()]);
- }
-
- $this->dependencies[$dependency->getName()] = $dependency;
-
- return $this;
+ public function __construct(
+ private readonly ?ContainerInterface $parent = null,
+ ) {
}
/**
- * Get a dependency.
- *
- * @param string $name
+ * Register a dependency factory on the current container.
*
- * @return mixed
+ * @param callable(ContainerInterface): mixed $factory
*/
- public function get(string $name): mixed
+ public function set(string $key, callable $factory): static
{
- if (!\array_key_exists($name, $this->dependencies)) {
- throw new Exception('Failed to find dependency: "' . $name . '"');
- }
-
- return $this->inject($this->dependencies[$name]);
- }
+ $this->definitions[$key] = $factory;
+ unset($this->resolved[$key]);
- /**
- * Check if a dependency exists.
- *
- * @param string $name
- *
- * @return bool
- */
- public function has(string $name): bool
- {
- return \array_key_exists($name, $this->dependencies);
+ return $this;
}
/**
- * Resolve the dependencies of a given injection.
+ * Resolve an entry from the current container or its parent chain.
*
- * @param Injection $injection
- * @param bool $fresh
*
- * @return mixed
+ * @throws ContainerExceptionInterface
*/
- public function inject(Injection $injection, bool $fresh = false): mixed // Route
+ public function get(string $id): mixed
{
- if (\array_key_exists($injection->getName(), $this->instances) && !$fresh) {
- return $this->instances[$injection->getName()];
+ if (\array_key_exists($id, $this->resolved)) {
+ return $this->resolved[$id];
}
- $arguments = [];
-
- foreach ($injection->getDependencies() as $dependency) {
-
- if (\array_key_exists($dependency, $this->instances)) {
- $arguments[] = $this->instances[$dependency];
- continue;
+ if (\array_key_exists($id, $this->definitions)) {
+ if (isset($this->resolving[$id])) {
+ throw new ContainerException('Circular dependency detected for "'.$id.'".');
}
- if (!\array_key_exists($dependency, $this->dependencies)) {
- throw new Exception('Failed to find dependency: "' . $dependency . '"');
+ $this->resolving[$id] = true;
+
+ try {
+ $resolved = ($this->definitions[$id])($this);
+ } catch (NotFoundException|ContainerExceptionInterface $exception) {
+ throw $exception;
+ } catch (\Throwable $exception) {
+ throw new ContainerException(
+ 'Failed to resolve dependency "'.$id.'".',
+ previous: $exception
+ );
+ } finally {
+ unset($this->resolving[$id]);
}
- $arguments[] = $this->get($dependency);
+ $this->resolved[$id] = $resolved;
+ return $resolved;
}
- $resolved = \call_user_func_array($injection->getCallback(), $arguments);
+ if ($this->parent instanceof ContainerInterface) {
+ return $this->parent->get($id);
+ }
- $this->instances[$injection->getName()] = $resolved;
+ throw new NotFoundException('Dependency not found: '.$id);
+ }
- return $resolved;
+ public function has(string $id): bool
+ {
+ if (\array_key_exists($id, $this->definitions)) {
+ return true;
+ }
+
+ return $this->parent?->has($id) ?? false;
}
+
/**
- * Refresh a dependency
- *
- * @param string $name
- * @return self
- * @throws Exception
+ * Create a child container that falls back to the current container.
*/
- public function refresh(string $name): self
+ public function scope(): static
{
- if(\array_key_exists($name, $this->instances)) {
- unset($this->instances[$name]);
- }
-
- return $this;
+ return new static($this);
}
}
diff --git a/src/DI/Dependency.php b/src/DI/Dependency.php
index 906a629..1846fea 100644
--- a/src/DI/Dependency.php
+++ b/src/DI/Dependency.php
@@ -2,6 +2,31 @@
namespace Utopia\DI;
-class Dependency extends Injection
+use Psr\Container\ContainerInterface;
+
+class Dependency
{
+ /**
+ * @param string[] $injections
+ * @param callable $callback
+ */
+ public function __construct(
+ private readonly array $injections,
+ private $callback,
+ ) {
+ }
+
+ /**
+ * Resolve the configured injections from the container and invoke the callback.
+ */
+ public function __invoke(ContainerInterface $container): mixed
+ {
+ $arguments = [];
+
+ foreach ($this->injections as $injection) {
+ $arguments[$injection] = $container->get($injection);
+ }
+
+ return ($this->callback)(...$arguments);
+ }
}
diff --git a/src/DI/Exceptions/ContainerException.php b/src/DI/Exceptions/ContainerException.php
new file mode 100644
index 0000000..bc4b4fc
--- /dev/null
+++ b/src/DI/Exceptions/ContainerException.php
@@ -0,0 +1,10 @@
+name = $name;
- return $this;
- }
-
- /**
- * Get the value of name
- *
- * @return string
- */
- public function getName(): string
- {
- return $this->name;
- }
-
- /**
- * Set Callback
- *
- * @param mixed $callback
- * @return self
- */
- public function setCallback(mixed $callback): self
- {
- $this->callback = $callback;
-
- return $this;
- }
-
- /**
- * Get the value of callback
- *
- * @return mixed
- */
- public function getCallback(): mixed
- {
- return $this->callback;
- }
-
- /**
- * Get the value of dependencies
- *
- * @return string[]
- */
- public function getDependencies(): array
- {
- return $this->dependencies;
- }
-
- /**
- * Depenedency
- *
- * @param string $name
- * @return self
- *
- * @throws Exception
- */
- public function inject(string $name): self
- {
- if (array_key_exists($name, $this->dependencies)) {
- throw new Exception('Dependency already declared for '.$name);
- }
-
- $this->dependencies[] = $name;
-
- return $this;
- }
-}
diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php
index 57af3ec..7ad2fcb 100644
--- a/tests/ContainerTest.php
+++ b/tests/ContainerTest.php
@@ -1,43 +1,216 @@
container = new Container();
- $user = new Dependency();
- $user
- ->setName('user')
- ->inject('age')
- ->setCallback(fn ($age) => 'John Doe is '.$age.' years old.');
+ $this->container
+ ->set('age', fn (ContainerInterface $container): int => 25)
+ ->set(
+ 'user',
+ fn (ContainerInterface $container): string => 'John Doe is '.$container->get('age').' years old.'
+ )
;
+ }
+
+ public function tearDown(): void
+ {
+ $this->container = null;
+ }
+
+ public function testImplementsPsrContainerInterface(): void
+ {
+ $this->assertInstanceOf(ContainerInterface::class, $this->container);
+ }
+
+ public function testResolution(): void
+ {
+ $this->assertSame('John Doe is 25 years old.', $this->container->get('user'));
+ }
- $age = new Dependency();
- $age
- ->setName('age')
- ->setCallback(fn () => 25);
+ public function testCanRegisterDependencyObjects(): void
+ {
+ $container = new Container();
+
+ $container
+ ->set(
+ key: 'age',
+ factory: new Dependency(
+ injections: [],
+ callback: fn (): int => 25
+ )
+ )
+ ->set(
+ key: 'john',
+ factory: new Dependency(
+ injections: ['age'],
+ callback: fn (int $age): string => 'John Doe is '.$age.' years old.'
+ )
+ )
;
- $this->container
- ->set($user)
- ->set($age)
+ $this->assertSame('John Doe is 25 years old.', $container->get('john'));
+ }
+
+ public function testDependencyOrderDoesNotNeedToMatchCallbackParameterOrder(): void
+ {
+ $container = new Container();
+
+ $container
+ ->set(
+ key: 'a',
+ factory: new Dependency(
+ injections: [],
+ callback: fn (): string => 'value-a'
+ )
+ )
+ ->set(
+ key: 'b',
+ factory: new Dependency(
+ injections: [],
+ callback: fn (): string => 'value-b'
+ )
+ )
+ ->set(
+ key: 'combined',
+ factory: new Dependency(
+ injections: ['a', 'b'],
+ callback: fn (string $b, string $a): string => "{$a}:{$b}"
+ )
+ )
+ ;
+
+ $this->assertSame('value-a:value-b', $container->get('combined'));
+ }
+
+ public function testFactoriesAreResolvedOncePerContainer(): void
+ {
+ $counter = 0;
+
+ $this->container->set('counter', function (ContainerInterface $container) use (&$counter): int {
+ $counter++;
+
+ return $counter;
+ });
+
+ $this->assertSame(1, $this->container->get('counter'));
+ $this->assertSame(1, $this->container->get('counter'));
+ }
+
+ public function testScopedContainersFallbackToParentDefinitions(): void
+ {
+ $request = $this->container->scope();
+
+ $this->assertSame('John Doe is 25 years old.', $request->get('user'));
+ $this->assertTrue($request->has('user'));
+ }
+
+ public function testScopedContainersCanOverrideParentDefinitions(): void
+ {
+ $request = $this->container->scope();
+
+ $request
+ ->set('age', fn (ContainerInterface $container): int => 30)
+ ->set(
+ 'user',
+ fn (ContainerInterface $container): string => 'John Doe is '.$container->get('age').' years old.'
+ )
;
+
+ $this->assertSame('John Doe is 30 years old.', $request->get('user'));
+ $this->assertSame('John Doe is 25 years old.', $this->container->get('user'));
+ }
+
+ public function testScopeUsesParentCacheUntilDefinitionsAreOverridden(): void
+ {
+ $counter = 0;
+
+ $this->container->set('counter', function (ContainerInterface $container) use (&$counter): int {
+ $counter++;
+
+ return $counter;
+ });
+
+ $request = $this->container->scope();
+
+ $this->assertSame(1, $this->container->get('counter'));
+ $this->assertSame(1, $request->get('counter'));
+
+ $request->set('counter', function (ContainerInterface $container) use (&$counter): int {
+ $counter++;
+
+ return $counter;
+ });
+
+ $this->assertSame(2, $request->get('counter'));
+ $this->assertSame(2, $request->get('counter'));
+ }
+
+ public function testCanCacheNullValues(): void
+ {
+ $counter = 0;
+
+ $this->container->set('nullable', function (ContainerInterface $container) use (&$counter): null {
+ $counter++;
+
+ return null;
+ });
+
+ $this->assertNull($this->container->get('nullable'));
+ $this->assertNull($this->container->get('nullable'));
+ $this->assertSame(1, $counter);
+ }
+
+ public function testMissingDependencyThrowsNotFoundException(): void
+ {
+ $this->expectException(NotFoundException::class);
+ $this->expectExceptionMessage('Dependency not found: missing');
+
+ $this->container->get('missing');
}
- public function testResolution()
+ public function testFactoryFailuresThrowContainerException(): void
{
- $this->assertEquals('John Doe is 25 years old.', $this->container->get('user'));
+ $this->container->set('broken', function (ContainerInterface $container): never {
+ throw new RuntimeException('boom');
+ });
+
+ try {
+ $this->container->get('broken');
+ $this->fail('Expected a container exception.');
+ } catch (ContainerException $exception) {
+ $this->assertSame('Failed to resolve dependency "broken".', $exception->getMessage());
+ $this->assertInstanceOf(RuntimeException::class, $exception->getPrevious());
+ $this->assertSame('boom', $exception->getPrevious()->getMessage());
+ }
+ }
+
+ public function testCircularDependenciesThrowContainerException(): void
+ {
+ $this->container
+ ->set('a', fn (ContainerInterface $container) => $container->get('b'))
+ ->set('b', fn (ContainerInterface $container) => $container->get('a'))
+ ;
+
+ $this->expectException(ContainerException::class);
+ $this->expectExceptionMessage('Circular dependency detected for "a".');
+
+ $this->container->get('a');
}
}
diff --git a/tools/rector/composer.json b/tools/rector/composer.json
new file mode 100644
index 0000000..7a416da
--- /dev/null
+++ b/tools/rector/composer.json
@@ -0,0 +1,18 @@
+{
+ "name": "utopia-php/di-rector",
+ "description": "Rector tooling for utopia-php/di",
+ "type": "project",
+ "license": "MIT",
+ "config": {
+ "platform": {
+ "php": "8.3.0"
+ }
+ },
+ "scripts": {
+ "refactor": "vendor/bin/rector process --config=../../rector.php",
+ "refactor:check": "vendor/bin/rector process --dry-run --config=../../rector.php"
+ },
+ "require-dev": {
+ "rector/rector": "^2.2"
+ }
+}
diff --git a/tools/rector/composer.lock b/tools/rector/composer.lock
new file mode 100644
index 0000000..2eb50f1
--- /dev/null
+++ b/tools/rector/composer.lock
@@ -0,0 +1,135 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "c7361960ab6626c5811289d496a9c742",
+ "packages": [],
+ "packages-dev": [
+ {
+ "name": "phpstan/phpstan",
+ "version": "2.1.40",
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
+ "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
+ },
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPStan - PHP Static Analysis Tool",
+ "keywords": [
+ "dev",
+ "static analysis"
+ ],
+ "support": {
+ "docs": "https://phpstan.org/user-guide/getting-started",
+ "forum": "https://github.com/phpstan/phpstan/discussions",
+ "issues": "https://github.com/phpstan/phpstan/issues",
+ "security": "https://github.com/phpstan/phpstan/security/policy",
+ "source": "https://github.com/phpstan/phpstan-src"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/phpstan",
+ "type": "github"
+ }
+ ],
+ "time": "2026-02-23T15:04:35+00:00"
+ },
+ {
+ "name": "rector/rector",
+ "version": "2.3.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/rectorphp/rector.git",
+ "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/rectorphp/rector/zipball/bbd37aedd8df749916cffa2a947cfc4714d1ba2c",
+ "reference": "bbd37aedd8df749916cffa2a947cfc4714d1ba2c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0",
+ "phpstan/phpstan": "^2.1.38"
+ },
+ "conflict": {
+ "rector/rector-doctrine": "*",
+ "rector/rector-downgrade-php": "*",
+ "rector/rector-phpunit": "*",
+ "rector/rector-symfony": "*"
+ },
+ "suggest": {
+ "ext-dom": "To manipulate phpunit.xml via the custom-rule command"
+ },
+ "bin": [
+ "bin/rector"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Instant Upgrade and Automated Refactoring of any PHP code",
+ "homepage": "https://getrector.com/",
+ "keywords": [
+ "automation",
+ "dev",
+ "migration",
+ "refactoring"
+ ],
+ "support": {
+ "issues": "https://github.com/rectorphp/rector/issues",
+ "source": "https://github.com/rectorphp/rector/tree/2.3.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/tomasvotruba",
+ "type": "github"
+ }
+ ],
+ "time": "2026-02-22T09:45:50+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {},
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {},
+ "platform-dev": {},
+ "platform-overrides": {
+ "php": "8.3.0"
+ },
+ "plugin-api-version": "2.6.0"
+}