diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000..5e9a93ea50d32 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.yml] +indent_size = 2 diff --git a/.env b/.env new file mode 100644 index 0000000000000..882df24b0b40e --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +APP_ENV=dev +APP_DEBUG=true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000..24727fa908c22 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,34 @@ +# Autodetect text files +* text=auto eol=lf + +# ...Unless the name matches the following overriding patterns + +# Definitively text files +*.php text +*.css text +*.js text +*.txt text +*.md text +*.xml text +*.json text +*.bat text +*.sql text +*.yml text + +# Ensure those won't be messed up with +*.png binary +*.jpg binary +*.gif binary +*.ttf binary + +# Ignore some meta files when creating an archive of this repository +/.github export-ignore +/.gitattributes export-ignore +/LICENSE.md export-ignore +/README.md export-ignore +/composer.lock export-ignore + +# Avoid merge conflicts in CHANGELOG +# https://about.gitlab.com/2015/02/10/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders/ +/CHANGELOG.md merge=union + diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000..eb64a88110383 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,67 @@ +# Yii Contributor Code of Conduct + +## Our Pledge + +As contributors and maintainers of this project, and in order to keep Yii community open and welcoming, we ask to respect all community members. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Personal attacks +* Trolling or insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing other's private information, such as physical or electronic + addresses, without explicit permission +* Other conduct which could reasonably be considered inappropriate in + a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in response +to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, +commits, code, wiki edits, issues, and other contributions that are not aligned to this +Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors +that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when +an individual is representing the project or its community. Examples of representing +a project or community include posting via an official social media account, +within project GitHub, official forum or acting as an appointed representative at +an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported +by contacting core team members. All complaints will be reviewed and investigated +and will result in a response that is deemed necessary and appropriate to the circumstances. +The project team is obligated to maintain confidentiality with regard to the reporter of +an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith +may face temporary or permanent repercussions as determined by other members of +the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4.0, available at +[https://contributor-covenant.org/version/1/4/][version] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/4/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000000000..28737bdfaf3b0 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Prerequisites + +- [Yii goal and values](https://github.com/yiisoft/docs/blob/master/001-yii-values.md) +- [Namespaces](https://github.com/yiisoft/docs/blob/master/004-namespaces.md) +- [Git commit messages](https://github.com/yiisoft/docs/blob/master/006-git-commit-messages.md) +- [Exceptions](https://github.com/yiisoft/docs/blob/master/007-exceptions.md) +- [Interfaces](https://github.com/yiisoft/docs/blob/master/008-interfaces.md) + +# Getting started + +Since Yii 3 consists of many packages, we have a [special development tool](https://github.com/yiisoft/docs/blob/master/005-development-tool.md). + +1. [Clone the repository](https://github.com/yiisoft/yii-dev-tool). + +2. [Set up your own fork](https://github.com/yiisoft/yii-dev-tool#using-your-own-fork). + +3. Now you are ready. Fork any package listed in `packages.php` and do `./yii-dev install username/package`. + +If you don't have any particular package in mind to start with: + +- [Check roadmap](https://github.com/yiisoft/docs/blob/master/003-roadmap.md). +- Check package issues at github. Usually there are some. +- Ask @samdark. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000000..f0dc5312db888 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +open_collective: yiisoft +github: [yiisoft] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000000..b748c2dac58e2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,16 @@ + + +### What steps will reproduce the problem? + +### What is the expected result? + +### What do you get instead? + + +### Additional info + +| Q | A +| ---------------- | --- +| Version | 1.0.? +| PHP version | +| Operating system | diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..4a3e8ace98e2c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +| Q | A +| ------------- | --- +| Is bugfix? | ✔️/❌ +| New feature? | ✔️/❌ +| Breaks BC? | ✔️/❌ +| Fixed issues | comma-separated list of tickets # fixed by the PR, if any diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000000..ba093183275b8 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,6 @@ +# Security Policy + +Please use the [security issue form](https://www.yiiframework.com/security) to report to us any security issue you +find in Yii. DO NOT use the issue tracker or discuss it in the public forum as it will cause more damage than help. + +Please note that as a non-commercial OpenSource project we are not able to pay bounties at the moment. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..d7ebdbfdbff9b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions. + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + # Too noisy. See https://github.community/t/increase-if-necessary-for-github-actions-in-dependabot/179581 + open-pull-requests-limit: 0 + + # Maintain dependencies for Composer + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "daily" + versioning-strategy: increase-if-necessary diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000000..28d296b8a9b65 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,77 @@ +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'psalm.xml' + + push: + branches: ['master'] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'psalm.xml' + +name: build + +jobs: + codeception: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + env: + key: cache-v1 + APP_C3: true + APP_ENV: test + APP_DEBUG: false + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + - windows-latest + php: + - "8.5" + + steps: + - name: Checkout. + uses: actions/checkout@v4 + + - name: Install PHP with extensions. + uses: shivammathur/setup-php@v2 + with: + coverage: false + extensions: fileinfo, intl + ini-values: date.timezone='UTC', register_argc_argv=On + php-version: ${{ matrix.php }} + + - name: Install Composer dependencies + uses: ramsey/composer-install@v3 + + - name: Run codeception build. + run: vendor/bin/codecept build + + - name: Run tests with codeception with code coverage with shell bash. + if: matrix.os == 'ubuntu-latest' + run: vendor/bin/codecept run --coverage --coverage-xml --disable-coverage-php + + - name: Run tests with codeception with code coverage with shell powershell. + if: matrix.os == 'windows-latest' + run: vendor/bin/codecept run + shell: powershell + + - name: Upload coverage to Codecov. + if: matrix.os == 'ubuntu-latest' + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: runtime/tests/_output/coverage.xml diff --git a/.github/workflows/composer-dependency-analyzer.yml b/.github/workflows/composer-dependency-analyzer.yml new file mode 100644 index 0000000000000..7f5b6dc24c221 --- /dev/null +++ b/.github/workflows/composer-dependency-analyzer.yml @@ -0,0 +1,55 @@ +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'phpunit.xml.dist' + - 'psalm.xml' + + push: + branches: ['master'] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'phpunit.xml.dist' + - 'psalm.xml' + +name: Composer dependency analyzer + +jobs: + analyzer: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + php: + - "8.5" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + coverage: none + php-version: ${{ matrix.php }} + tools: composer:v2, cs2pr + + - name: Install Composer dependencies + uses: ramsey/composer-install@v3 + + - name: Run composer dependency analyzer + run: vendor/bin/composer-dependency-analyser --config=composer-dependency-analyser.php diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml new file mode 100644 index 0000000000000..56ae55a4cfb22 --- /dev/null +++ b/.github/workflows/cs.yml @@ -0,0 +1,44 @@ +name: Code Style + +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'psalm.xml' + +jobs: + cs-fix: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.5 + tools: composer:v2 + coverage: none + + - name: Install Composer dependencies + uses: "ramsey/composer-install@v4" + + - name: Run PHP CS Fixer + run: ./vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php + + - name: Run Rector + run: ./vendor/bin/rector --output-format=github + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v7 + with: + commit_message: "Apply PHP CS Fixer and Rector changes (CI)" + file_pattern: '*.php' + disable_globbing: true diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000000000..e4c21f56ae55a --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,53 @@ +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'phpunit.xml.dist' + + push: + branches: ['master'] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + - 'infection.json.dist' + - 'phpunit.xml.dist' + +name: static analysis + +jobs: + psalm: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + php: + - "8.5" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + coverage: none + php-version: ${{ matrix.php }} + tools: composer:v2, cs2pr + + - name: Install Composer dependencies + uses: ramsey/composer-install@v3 + + - name: Static analysis + run: vendor/bin/psalm --shepherd --stats --output-format=checkstyle --no-cache --php-version=${{ matrix.php }} | cs2pr --graceful-warnings --colorize diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000..806d488fcbe24 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# phpstorm project files +.idea + +# netbeans project files +nbproject + +# zend studio for eclipse project files +.buildpath +.project +.settings + +# sublime text project / workspace files +*.sublime-project +*.sublime-workspace + +# windows thumbnail cache +Thumbs.db + +# Mac DS_Store Files +.DS_Store + +# composer vendor dir +/vendor + +# Codeception C3 +c3.php diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000000000..97880909973ad --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,32 @@ +in([ + $root . '/config', + $root . '/src', + $root . '/tests', + ]) + ->exclude([ + 'Support/_generated', + ]) + ->append([ + $root . '/public/index.php', + ]); + +return new Config() + ->setCacheFile(__DIR__ . '/runtime/cache/.php-cs-fixer.cache') + ->setParallelConfig(ParallelConfigFactory::detect()) + ->setRules([ + '@PER-CS3.0' => true, + 'no_unused_imports' => true, + ]) + ->setFinder($finder); diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000..fd893948a143b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM php:8.5-cli + +RUN apt -y update && apt -y upgrade + +# Required tools +RUN apt -y install \ + unzip \ + git \ + libicu-dev + +# PHP extensions +RUN docker-php-ext-install -j$(nproc) \ + intl + +# Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Locale +ENV LC_ALL=C.UTF-8 + +# Xdebug +RUN pecl install xdebug-3.5.0 \ + && docker-php-ext-enable xdebug + +# PHP configuration +RUN mv $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini + +WORKDIR /app diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000000..bc5674fe4706c --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,29 @@ +Copyright © 2008 by Yii Software (https://www.yiiframework.com/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Yii Software nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000..3bf2b76bb0792 --- /dev/null +++ b/Makefile @@ -0,0 +1,66 @@ +.DEFAULT_GOAL := help + +# Current user ID and group ID except MacOS where it conflicts with Docker abilities +ifeq ($(shell uname), Darwin) + export UID=1000 + export GID=1000 +else + export UID=$(shell id -u) + export GID=$(shell id -g) +endif + +export COMPOSE_PROJECT_NAME=demo-diary + +init: build composer-install codecept-build + +build: ## Build docker image + docker compose build + +up: ## Up the dev environment + docker compose up -d + +down: ## Down the dev environment + docker compose down --remove-orphans + +clear: ## Remove development docker containers and volumes + docker compose down --volumes --remove-orphans + +shell: ## Get into container shell + docker compose exec app /bin/bash + +composer-install: ## Run composer install + docker compose run --rm app composer install + +composer-update: ## Run composer update + docker compose run --rm app composer update + +codecept-build: ## Run codeception build + docker compose run --rm app composer codecept-build + +test: + docker compose run --rm app composer test + +psalm: ## Run psalm static analysis + docker compose run --rm app composer psalm + +rector: ## Run rector code refactoring + docker compose run --rm app composer rector + +composer-dependency-analyzer: ## Run composer dependency analyzer + docker compose run --rm app composer composer-dependency-analyser + +cs-fix: ## Run code style fix + docker compose run --rm app composer cs-fix + +migrate-up: ## Run migrations + docker compose run --rm app ./yii migrate:up --force-yes + +fake-data: ## Generate fake data + docker compose run --rm app ./yii fake-data + +create-admin: ## Create admin user (admin / q1w2e3r4) + docker compose run --rm app ./yii user:create-admin admin q1w2e3r4 + +# Output the help for each task, see https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html +help: ## This help. + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..04af1b0687027 --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +

+ + Yii + +

Yii3 Demo Diary

+
+

+ +[![Build status](https://github.com/yiisoft/demo-diary/actions/workflows/build.yml/badge.svg)](https://github.com/yiisoft/demo-diary/actions/workflows/build.yml) +[![Code Coverage](https://codecov.io/gh/yiisoft/demo-diary/branch/master/graph/badge.svg?token=TDZ2bErTcN)](https://codecov.io/gh/yiisoft/demo-diary) +[![static analysis](https://github.com/yiisoft/demo-diary/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/demo-diary/actions?query=workflow%3A%22static+analysis%22) +[![type-coverage](https://shepherd.dev/github/yiisoft/demo-diary/coverage.svg)](https://shepherd.dev/github/yiisoft/demo-diary) + +Demo diary application built on Yii3 framework using **vertical slice architecture** — code is organized +by features rather than technical layers. Demonstrates user management, category and post CRUD, +authentication, and database migrations. + +**Features:** + +- Diary with categories and posts (create, read, update, delete) +- User management with [GridView](https://github.com/yiisoft/yii-dataview) list powered by [htmx](https://htmx.org/) — pagination, sorting, and filtering work via AJAX without full page reloads +- Authentication and access control +- Database migrations via [Yii DB Migration](https://github.com/yiisoft/yii-db-migration) + +## Requirements + +- PHP 8.5 or higher. + +## General usage + +1. Clone this repository. + +2. Move to your project root directory. + +3. Install composer dependencies: + +```shell +composer install + +# or via docker +make init +``` + +4. Apply migrations: + +```shell +# Linux +./yii migrate:up + +# Windows +yii migrate:up + +# or via docker +make migrate-up +``` + +5. Run application: + +```shell +# Linux +./yii serve + +# Windows +yii server + +# or via docker +make up +``` + +The application will be started on http://127.0.0.1:8080/. + + +## Support + +If you need help or have a question, check out [Yii Community Resources](https://www.yiiframework.com/community). + +## License + +The Yii3 Demo Diary is free software. It is released under the terms of the BSD License. +Please see [`LICENSE`](./LICENSE.md) for more information. + +Maintained by [Yii Software](https://www.yiiframework.com/). + +## Support the project + +[![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft) + +## Follow updates + +[![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/) +[![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter&logoColor=1DA1F2&labelColor=555555?style=flat)](https://twitter.com/yiiframework) +[![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en) +[![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk) +[![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack) diff --git a/assets/main/logo.svg b/assets/main/logo.svg new file mode 100644 index 0000000000000..6e9e879aa7117 --- /dev/null +++ b/assets/main/logo.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/main/site.css b/assets/main/site.css new file mode 100644 index 0000000000000..2dceb28003d62 --- /dev/null +++ b/assets/main/site.css @@ -0,0 +1,28 @@ +.loginForm { + max-width: 360px; + padding: 1.4rem 1.6rem; + box-shadow: 0 0 120px #bbb; + background: rgba(255, 255, 255, 0.8); + border-radius: 12px; +} + +.loginForm_logo { + text-align: center; + padding-bottom: 24px; +} + +.loginForm_login { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.loginForm_password { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.loginForm .form-floating:focus-within { + z-index: 2; +} diff --git a/codeception.yml b/codeception.yml new file mode 100644 index 0000000000000..e33d57222139b --- /dev/null +++ b/codeception.yml @@ -0,0 +1,29 @@ +namespace: App\Tests +support_namespace: Support +bootstrap: bootstrap.php + +settings: + shuffle: true + colors: true + +params: + - tests/.env + +paths: + tests: tests + output: tests/_output + data: tests/Support/Data + support: tests/Support + +coverage: + enabled: true + show_uncovered: true + show_only_summary: true + include: + - src/* + - public/index.php + - yii + +extensions: + enabled: + - Codeception\Extension\RunFailed diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php new file mode 100644 index 0000000000000..f27b8a3a60c13 --- /dev/null +++ b/composer-dependency-analyser.php @@ -0,0 +1,20 @@ +disableComposerAutoloadPathScan() + ->setFileExtensions(['php']) + ->addPathToScan($root . '/src', isDev: false) + ->addPathToScan($root . '/config', isDev: false) + ->addPathToScan($root . '/public/index.php', isDev: false) + ->addPathToScan($root . '/yii', isDev: false) + ->addPathToScan($root . '/tests', isDev: true) + ->ignoreErrorsOnPackages( + ['yiisoft/config', 'yiisoft/router-fastroute', 'yiisoft/request-provider'], + [ErrorType::UNUSED_DEPENDENCY], + ); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000000..ccb83eb301a69 --- /dev/null +++ b/composer.json @@ -0,0 +1,139 @@ +{ + "name": "yiisoft/app", + "type": "project", + "description": "Yii3 Demo Diary", + "keywords": [ + "yii3", + "demo", + "application" + ], + "license": "BSD-3-Clause", + "support": { + "issues": "https://github.com/yiisoft/app/issues?state=open", + "source": "https://github.com/yiisoft/app", + "forum": "https://www.yiiframework.com/forum/", + "wiki": "https://www.yiiframework.com/wiki/", + "irc": "ircs://irc.libera.chat:6697/yii", + "chat": "https://t.me/yii3en" + }, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/yiisoft" + }, + { + "type": "github", + "url": "https://github.com/sponsors/yiisoft" + } + ], + "scripts": { + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@php ./yii serve" + ], + "test": "php -d register_argc_argv=On vendor/bin/codecept run", + "codecept-build": "php -d register_argc_argv=On vendor/bin/codecept build", + "psalm": "psalm", + "cs-fix": "php-cs-fixer fix --config=.php-cs-fixer.php --diff", + "rector": "rector", + "composer-dependency-analyser": "composer-dependency-analyser" + }, + "require": { + "php": "^8.5", + "ext-filter": "*", + "ext-intl": "*", + "ext-mbstring": "*", + "fakerphp/faker": "^1.24.1", + "httpsoft/http-message": "^1.1.6", + "psr/container": "^2.0.2", + "psr/http-factory": "^1.1", + "psr/http-message": "^2.0", + "psr/http-server-handler": "^1.0.2", + "psr/http-server-middleware": "^1.0.2", + "psr/log": "^3.0.2", + "ramsey/uuid": "^4.9.2", + "symfony/console": "^8.0.8", + "vlucas/phpdotenv": "^5.6.3", + "yiisoft/active-record": "^1.0.2", + "yiisoft/aliases": "^3.1.1", + "yiisoft/assets": "^5.1.2", + "yiisoft/auth": "^3.2.1", + "yiisoft/cache-file": "^3.2", + "yiisoft/config": "^1.6.2", + "yiisoft/csrf": "^2.2.3", + "yiisoft/data": "^2", + "yiisoft/data-db": "^1", + "yiisoft/data-response": "^2.2", + "yiisoft/db": "^2.0.1", + "yiisoft/db-migration": "^2.0.1", + "yiisoft/db-sqlite": "^2", + "yiisoft/definitions": "^3.4.1", + "yiisoft/di": "^1.4.1", + "yiisoft/error-handler": "^4.3.2", + "yiisoft/form": "^1.5.2", + "yiisoft/form-model": "^1.1.1", + "yiisoft/html": "^4", + "yiisoft/http": "^1.3", + "yiisoft/hydrator": "^1.6.3", + "yiisoft/injector": "^1.2.1", + "yiisoft/input-http": "^1.0.1", + "yiisoft/log": "^2.2.1", + "yiisoft/log-target-file": "^3.1", + "yiisoft/middleware-dispatcher": "^5.4", + "yiisoft/rbac": "^2.1.2", + "yiisoft/rbac-db": "^2.1", + "yiisoft/rbac-php": "^2.0", + "yiisoft/request-body-parser": "^1.2.1", + "yiisoft/request-provider": "^1.3", + "yiisoft/router": "^4.0.2", + "yiisoft/router-fastroute": "^4.0.3", + "yiisoft/security": "^1.2", + "yiisoft/session": "^3.0.1", + "yiisoft/strings": "^2.7", + "yiisoft/user": "^2.3.2", + "yiisoft/validator": "^2.5.1", + "yiisoft/view": "^12.2.4", + "yiisoft/widget": "^2.2.2", + "yiisoft/yii-console": "^2.4.2", + "yiisoft/yii-dataview": "^1.1", + "yiisoft/yii-http": "^1.1.1", + "yiisoft/yii-runner-console": "^2.2.1", + "yiisoft/yii-runner-http": "^3.2.1", + "yiisoft/yii-view-renderer": "^7.4.1" + }, + "require-dev": { + "codeception/c3": "^2.9", + "codeception/codeception": "^5.3.5", + "codeception/module-asserts": "^3.3.0", + "codeception/module-cli": "^2.0.1", + "codeception/module-phpbrowser": "^4.0.0", + "friendsofphp/php-cs-fixer": "^3.94.2", + "phpunit/phpunit": "^13.0.6", + "rector/rector": "^2.3.9", + "roave/security-advisories": "dev-latest", + "shipmonk/composer-dependency-analyser": "^1.8.4", + "vimeo/psalm": "^6.16.1" + }, + "autoload": { + "psr-4": { + "App\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests" + } + }, + "extra": { + "config-plugin-file": "config/configuration.php" + }, + "config": { + "sort-packages": true, + "bump-after-update": true, + "allow-plugins": { + "yiisoft/config": true, + "codeception/c3": true, + "composer/installers": true + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000000000..18ea5be7e7e10 --- /dev/null +++ b/composer.lock @@ -0,0 +1,15057 @@ +{ + "_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": "43eb846d38f18be356d6f2d7eaf1e7cc", + "packages": [ + { + "name": "alexkart/curl-builder", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/alexkart/curl-builder.git", + "reference": "ce9224d8a33625059ae1c549b101061cf8d8bc27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/alexkart/curl-builder/zipball/ce9224d8a33625059ae1c549b101061cf8d8bc27", + "reference": "ce9224d8a33625059ae1c549b101061cf8d8bc27", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "psr/http-message": "^2.0" + }, + "require-dev": { + "nyholm/psr7": "^1.3", + "phan/phan": "^5.4", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Alexkart\\CurlBuilder\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexander Kartavenko", + "email": "askemailbox@gmail.com" + } + ], + "description": "PSR-7 compatible curl builder.", + "support": { + "issues": "https://github.com/alexkart/curl-builder/issues", + "source": "https://github.com/alexkart/curl-builder/tree/1.1.0" + }, + "time": "2025-06-03T23:28:32+00:00" + }, + { + "name": "brick/math", + "version": "0.14.8", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", + "shasum": "" + }, + "require": { + "php": "^8.2" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" + }, + "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.14.8" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2026-02-10T14:33:43+00:00" + }, + { + "name": "cebe/markdown", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/cebe/markdown.git", + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86", + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86", + "shasum": "" + }, + "require": { + "lib-pcre": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "cebe/indent": "*", + "facebook/xhprof": "*@dev", + "phpunit/phpunit": "4.1.*" + }, + "bin": [ + "bin/markdown" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "cebe\\markdown\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Creator" + } + ], + "description": "A super fast, highly extensible markdown parser for PHP", + "homepage": "https://github.com/cebe/markdown#readme", + "keywords": [ + "extensible", + "fast", + "gfm", + "markdown", + "markdown-extra" + ], + "support": { + "issues": "https://github.com/cebe/markdown/issues", + "source": "https://github.com/cebe/markdown" + }, + "time": "2018-03-26T11:24:36+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": "graham-campbell/result-type", + "version": "v1.1.4", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.5" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:43:20+00:00" + }, + { + "name": "httpsoft/http-message", + "version": "1.1.6", + "source": { + "type": "git", + "url": "https://github.com/httpsoft/http-message.git", + "reference": "f6c88e2189b9f75f10dfaeb0a85c56ea04a53c19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/httpsoft/http-message/zipball/f6c88e2189b9f75f10dfaeb0a85c56ea04a53c19", + "reference": "f6c88e2189b9f75f10dfaeb0a85c56ea04a53c19", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1|^2.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "php-http/psr7-integration-tests": "^1.3", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7", + "vimeo/psalm": "^4.9|^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "HttpSoft\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Evgeniy Zyubin", + "email": "mail@devanych.ru", + "homepage": "https://devanych.ru/", + "role": "Founder and lead developer" + } + ], + "description": "Strict and fast implementation of PSR-7 and PSR-17", + "homepage": "https://httpsoft.org/", + "keywords": [ + "http", + "http-message", + "php", + "psr-17", + "psr-7" + ], + "support": { + "docs": "https://httpsoft.org/docs/message", + "issues": "https://github.com/httpsoft/http-message/issues", + "source": "https://github.com/httpsoft/http-message" + }, + "time": "2024-08-09T07:13:21+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.5", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "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": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:41:33+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-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/http-server-handler", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "support": { + "source": "https://github.com/php-fig/http-server-handler/tree/1.0.2" + }, + "time": "2023-04-10T20:06:20+00:00" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-middleware/issues", + "source": "https://github.com/php-fig/http-server-middleware/tree/1.0.2" + }, + "time": "2023-04-11T06:14:47+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": "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.2", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "8429c78ca35a09f27565311b98101e2826affde0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", + "reference": "8429c78ca35a09f27565311b98101e2826affde0", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "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.2" + }, + "time": "2025-12-14T04:43:48+00:00" + }, + { + "name": "symfony/console", + "version": "v8.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/7113778e2e91f4709cb3194a75dfa9c0d028d94d", + "reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.4|^8.0" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.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/v8.0.9" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-29T15:02:55+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/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/polyfill-ctype", + "version": "v1.37.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", + "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.37.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": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.37.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/4864388bfbd3001ce88e234fab652acd91fdc57e", + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e", + "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.37.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": "2026-04-26T13:13:48+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.37.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.37.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.37.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", + "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.37.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": "2026-04-10T17:25:58+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "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.34.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": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:30:57+00:00" + }, + { + "name": "symfony/string", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "ae9488f874d7603f9d2dfbf120203882b645d963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/ae9488f874d7603f9d2dfbf120203882b645d963", + "reference": "ae9488f874d7603f9d2dfbf120203882b645d963", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^7.4|^8.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/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.3", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "955e7815d677a3eaa7075231212f2110983adecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.4", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.5", + "symfony/polyfill-ctype": "^1.26", + "symfony/polyfill-mbstring": "^1.26", + "symfony/polyfill-php80": "^1.26" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "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.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:49:13+00:00" + }, + { + "name": "yiisoft/access", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/access.git", + "reference": "434612e7a26108d0ec97223c882f3c4cafded037" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/access/zipball/434612e7a26108d0ec97223c882f3c4cafded037", + "reference": "434612e7a26108d0ec97223c882f3c4cafded037", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.66", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.8", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Access\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "An interface for checking access", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "access", + "interface", + "rbac", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/access/issues?state=open", + "source": "https://github.com/yiisoft/access", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T10:12:01+00:00" + }, + { + "name": "yiisoft/active-record", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/active-record.git", + "reference": "b1f825d53c9ce7aef7a68cc32629b62e7c4875d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/active-record/zipball/b1f825d53c9ce7aef7a68cc32629b62e7c4875d8", + "reference": "b1f825d53c9ce7aef7a68cc32629b62e7c4875d8", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/db": "^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "ext-pdo": "*", + "friendsofphp/php-cs-fixer": "^3.89.1", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.58", + "rector/rector": "^2.2.3", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/aliases": "^2.0", + "yiisoft/arrays": "^3.2", + "yiisoft/db-mssql": "^2.0", + "yiisoft/db-mysql": "^2.0", + "yiisoft/db-oracle": "^2.0", + "yiisoft/db-pgsql": "^2.0", + "yiisoft/db-sqlite": "^2.0", + "yiisoft/di": "^1.4", + "yiisoft/event-dispatcher": "^1.1", + "yiisoft/factory": "^1.3", + "yiisoft/psr-dummy-provider": "^1.0", + "yiisoft/test-support": "^3.0.2" + }, + "suggest": { + "yiisoft/arrays": "For \\Yiisoft\\Arrays\\ArrayableInterface support", + "yiisoft/db-mssql": "For MSSQL database support", + "yiisoft/db-mysql": "For MySQL database support", + "yiisoft/db-oracle": "For Oracle database support", + "yiisoft/db-pgsql": "For PostgreSQL database support", + "yiisoft/db-sqlite": "For SQLite database support", + "yiisoft/event-dispatcher": "For events support", + "yiisoft/factory": "For factory support" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\ActiveRecord\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Active record pattern implementation", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "Active Record", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/active-record/issues?state=open", + "source": "https://github.com/yiisoft/active-record", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-11T06:54:20+00:00" + }, + { + "name": "yiisoft/aliases", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/aliases.git", + "reference": "6f876dbf899f604fd3aefa3b3fd37e2ff2549ead" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/aliases/zipball/6f876dbf899f604fd3aefa3b3fd37e2ff2549ead", + "reference": "6f876dbf899f604fd3aefa3b3fd37e2ff2549ead", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.48", + "psr/container": "^2.0.2", + "rector/rector": "^2.1.2", + "spatie/phpunit-watcher": "^1.24.0", + "yiisoft/definitions": "^3.4", + "yiisoft/di": "^1.4", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Aliases\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Named paths and URLs storage", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "alias" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/aliases/issues?state=open", + "source": "https://github.com/yiisoft/aliases", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-04T12:53:43+00:00" + }, + { + "name": "yiisoft/arrays", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/arrays.git", + "reference": "8efada90e4fd540b3da476779bc1b7bd9319b62f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/arrays/zipball/8efada90e4fd540b3da476779bc1b7bd9319b62f", + "reference": "8efada90e4fd540b3da476779bc1b7bd9319b62f", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/strings": "^2.6" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpbench/phpbench": "^1.4.1", + "phpunit/phpunit": "^10.5.48", + "rector/rector": "^2.1.2", + "spatie/phpunit-watcher": "^1.24" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Arrays\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Array Helper", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "array", + "helper", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://forum.yiiframework.com/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/arrays/issues?state=open", + "source": "https://github.com/yiisoft/arrays", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-26T12:25:21+00:00" + }, + { + "name": "yiisoft/assets", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/assets.git", + "reference": "b79c9cef61c24c9b17dd8b1e7d2a692b7f98e370" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/assets/zipball/b79c9cef61c24c9b17dd8b1e7d2a692b7f98e370", + "reference": "b79c9cef61c24c9b17dd8b1e7d2a692b7f98e370", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "yiisoft/aliases": "^1.1 || ^2.0 || ^3.0", + "yiisoft/files": "^2.0", + "yiisoft/json": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "infection/infection": "^0.29.8", + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.52", + "rector/rector": "^2.1.4", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^6.13.1", + "yiisoft/di": "^1.4", + "yiisoft/test-support": "^3.0.2", + "yiisoft/yii-debug": "dev-master" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Assets\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Asset bundles and asset manager", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "assets", + "library", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/assets/issues?state=open", + "source": "https://github.com/yiisoft/assets", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T10:04:14+00:00" + }, + { + "name": "yiisoft/auth", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/auth.git", + "reference": "30f591448b96b7998c8ce66776aa178b53eee83e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/auth/zipball/30f591448b96b7998c8ce66776aa178b53eee83e", + "reference": "30f591448b96b7998c8ce66776aa178b53eee83e", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "maglnet/composer-require-checker": "^4.4", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.9", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.10", + "yiisoft/yii-debug": "dev-master || dev-php80" + }, + "type": "library", + "extra": { + "config-plugin": { + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Auth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii auth", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "auth", + "middleware" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/auth/issues?state=open", + "source": "https://github.com/yiisoft/auth", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-17T13:13:44+00:00" + }, + { + "name": "yiisoft/cache", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/cache.git", + "reference": "1f0fe8fac81632aa86b8feea73f2c7f11d7405d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/cache/zipball/1f0fe8fac81632aa86b8feea73f2c7f11d7405d2", + "reference": "1f0fe8fac81632aa86b8feea73f2c7f11d7405d2", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/simple-cache": "^2.0 || ^3.0" + }, + "provide": { + "psr/simple-cache-implementation": "2.0 || 3.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.46", + "rector/rector": "^2.0.17", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24.0", + "vimeo/psalm": "^5.26.1 || ^6.12", + "yiisoft/di": "^1.4.0" + }, + "suggest": { + "yiisoft/cache-apcu": "Allows to store cache using APCu PECL extension", + "yiisoft/cache-db": "Allows storing cache to the database", + "yiisoft/cache-file": "Allows storing cache to the files", + "yiisoft/cache-memcached": "Allows to store cache using Memcached PECL extension", + "yiisoft/cache-redis": "Allows storing cache to the Redis", + "yiisoft/cache-wincache": "Allows to store cache using WinCache PECL extension" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Cache\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Caching Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "cache", + "psr-16", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/cache/issues?state=open", + "source": "https://github.com/yiisoft/cache", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-11T05:44:17+00:00" + }, + { + "name": "yiisoft/cache-file", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/cache-file.git", + "reference": "484cde38f64504aeda89065339f9a313bc0691aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/cache-file/zipball/484cde38f64504aeda89065339f9a313bc0691aa", + "reference": "484cde38f64504aeda89065339f9a313bc0691aa", + "shasum": "" + }, + "require": { + "php": "^8.0", + "psr/simple-cache": "^2.0|^3.0" + }, + "provide": { + "psr/simple-cache-implementation": "1.0.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.4", + "php-mock/php-mock-phpunit": "^2.6", + "phpunit/phpunit": "^9.5", + "rector/rector": "^2.0", + "roave/infection-static-analysis-plugin": "^1.16", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^4.30|^5.21", + "yiisoft/aliases": "^3.0", + "yiisoft/di": "^1.2" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Cache\\File\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Caching Library - File Handler", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "cache", + "file", + "framework", + "psr-16", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/cache-file/issues?state=open", + "source": "https://github.com/yiisoft/cache-file", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-01-13T20:33:48+00:00" + }, + { + "name": "yiisoft/config", + "version": "1.6.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/config.git", + "reference": "a760058cd3434f057d0ab5b2f841021859b5084b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/config/zipball/a760058cd3434f057d0ab5b2f841021859b5084b", + "reference": "a760058cd3434f057d0ab5b2f841021859b5084b", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "8.1 - 8.5", + "symfony/console": "^5.4.11 || ^6.0.11 || ^7 || ^8", + "yiisoft/arrays": "^3.0", + "yiisoft/strings": "^2.0", + "yiisoft/var-dumper": "^1.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "composer/composer": "^2.8.5", + "phpunit/phpunit": "^10.5.44", + "rector/rector": "^2.0.7" + }, + "type": "composer-plugin", + "extra": { + "class": "Yiisoft\\Config\\Composer\\EventHandler", + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Composer plugin and a library for config assembling", + "homepage": "https://github.com/yiisoft/config", + "keywords": [ + "composer", + "config", + "plugin" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/config/issues?state=open", + "source": "https://github.com/yiisoft/config", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-19T19:11:23+00:00" + }, + { + "name": "yiisoft/cookies", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/cookies.git", + "reference": "7d83b86282b14fbf11c3bc7c01f0739c583d4421" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/cookies/zipball/7d83b86282b14fbf11c3bc7c01f0739c583d4421", + "reference": "7d83b86282b14fbf11c3bc7c01f0739c583d4421", + "shasum": "" + }, + "require": { + "php": "7.4.* || 8.0 - 8.5", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-message-implementation": "1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "yiisoft/http": "^1.2", + "yiisoft/security": "^1.0", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^3.8 || ^4.2", + "phpunit/phpunit": "^9.6.22", + "psr/clock": "^1.0", + "rector/rector": "^2.0.11", + "spatie/phpunit-watcher": "^1.23.6", + "yiisoft/test-support": "^1.4" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Cookies\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Convenient way to use cookies with PSR-7", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "cookie", + "cookies", + "psr-7" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/cookies/issues?state=open", + "source": "https://github.com/yiisoft/cookies", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-08T12:51:15+00:00" + }, + { + "name": "yiisoft/csrf", + "version": "2.2.3", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/csrf.git", + "reference": "e7e0d028b6cb4357a1a3b9403ab4fdf2285af2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/csrf/zipball/e7e0d028b6cb4357a1a3b9403ab4fdf2285af2af", + "reference": "e7e0d028b6cb4357a1a3b9403ab4fdf2285af2af", + "shasum": "" + }, + "require": { + "ext-hash": "*", + "php": "~7.4.0 || 8.0 - 8.5", + "psr/http-factory": "^1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-message-implementation": "1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/security": "^1.0", + "yiisoft/session": "^1.0 || ^2.0 || ^3.0", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^3.8 || ^4.2", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^9.6.23", + "rector/rector": "^2.0.16", + "roave/infection-static-analysis-plugin": "^1.18", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.8.8", + "yiisoft/di": "^1.1" + }, + "type": "library", + "extra": { + "config-plugin": { + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Csrf\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii CSRF Protection Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "breach", + "csrf", + "hmac", + "middleware", + "psr-15", + "stateless", + "synchronizer" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/csrf/issues?state=open", + "source": "https://github.com/yiisoft/csrf", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-18T21:03:10+00:00" + }, + { + "name": "yiisoft/data", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/data.git", + "reference": "12c4127fa6c2cd2c144212f841e01ab95c5a7796" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/data/zipball/12c4127fa6c2cd2c144212f841e01ab95c5a7796", + "reference": "12c4127fa6c2cd2c144212f841e01ab95c5a7796", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "yiisoft/arrays": "^3.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.91.3", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.60", + "rector/rector": "^2.2.14", + "spatie/phpunit-watcher": "^1.24" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Data\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Data providers, pagination and related abstractions", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "data processor", + "data provider", + "data reader", + "data writer", + "filter", + "pagination" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/data/issues?state=open", + "source": "https://github.com/yiisoft/data", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T15:25:47+00:00" + }, + { + "name": "yiisoft/data-db", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/data-db.git", + "reference": "225730cdf2125f9ef6e849229c31c7d73815cdba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/data-db/zipball/225730cdf2125f9ef6e849229c31c7d73815cdba", + "reference": "225730cdf2125f9ef6e849229c31c7d73815cdba", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/data": "^2.0", + "yiisoft/db": "^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.92.0", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.60", + "rector/rector": "^2.2.14", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.9.1", + "vlucas/phpdotenv": "^5.6.2", + "yiisoft/db-mssql": "^2.0", + "yiisoft/db-mysql": "^2.0", + "yiisoft/db-oracle": "^2.0", + "yiisoft/db-pgsql": "^2.0", + "yiisoft/db-sqlite": "^2.0", + "yiisoft/psr-dummy-provider": "^1.0.2", + "yiisoft/test-support": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Data\\Db\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Database query adapter for Yii Data", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "data provider", + "database", + "db" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/data-db/issues?state=open", + "source": "https://github.com/yiisoft/data-db", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T17:23:23+00:00" + }, + { + "name": "yiisoft/data-response", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/data-response.git", + "reference": "6b8c7a94fe6908baea5a933b187c5dcb1af2a0b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/data-response/zipball/6b8c7a94fe6908baea5a933b187c5dcb1af2a0b8", + "reference": "6b8c7a94fe6908baea5a933b187c5dcb1af2a0b8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "8.1 - 8.5", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/json": "^1.0", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.9.1", + "friendsofphp/php-cs-fixer": "^3.92.5", + "httpsoft/http-message": "^1.1.6", + "phpunit/phpunit": "^10.5.52", + "rector/rector": "^2.1.4", + "roave/infection-static-analysis-plugin": "^1.35", + "vimeo/psalm": "^5.26.1 || ^6.8.0", + "yiisoft/di": "^1.4", + "yiisoft/test-support": "^3.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\DataResponse\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Allows responding with data that is automatically converted into PSR-7 response", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "data", + "psr-7", + "response" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/data-response/issues?state=open", + "source": "https://github.com/yiisoft/data-response", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-02-23T08:36:46+00:00" + }, + { + "name": "yiisoft/db", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/db.git", + "reference": "fae72a47856f6947de7e5e18d7e5dd0b46ee1daa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/db/zipball/fae72a47856f6947de7e5e18d7e5dd0b46ee1daa", + "reference": "fae72a47856f6947de7e5e18d7e5dd0b46ee1daa", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": "8.1 - 8.5", + "psr/log": "^2.0|^3.0", + "psr/simple-cache": "^2.0|^3.0", + "psr/simple-cache-implementation": "*", + "yiisoft/db-implementation": "1.0.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.89.1", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/aliases": "^3.0", + "yiisoft/di": "^1.3", + "yiisoft/dummy-provider": "^1.1", + "yiisoft/event-dispatcher": "^1.1", + "yiisoft/log": "^2.1", + "yiisoft/psr-dummy-provider": "^1.0", + "yiisoft/test-support": "^3.0", + "yiisoft/var-dumper": "^1.7", + "yiisoft/yii-debug": "dev-master" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Db\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Database abstraction layer and query builder", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "database", + "dbal", + "query-builder", + "sql", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/db/issues/issues?state=open", + "source": "https://github.com/yiisoft/db", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-02-09T19:21:43+00:00" + }, + { + "name": "yiisoft/db-migration", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/db-migration.git", + "reference": "d4ea29b625d2c6cb77a935a9b51a654b305e36fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/db-migration/zipball/d4ea29b625d2c6cb77a935a9b51a654b305e36fe", + "reference": "d4ea29b625d2c6cb77a935a9b51a654b305e36fe", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "symfony/console": "^6.0 || ^7.0 || ^8.0", + "yiisoft/db": "^2.0", + "yiisoft/injector": "^1.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.89.2", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "yiisoft/db-sqlite": "^2.0", + "yiisoft/di": "^1.3", + "yiisoft/files": "^2.0", + "yiisoft/psr-dummy-provider": "^1.0", + "yiisoft/test-support": "^3.0.2", + "yiisoft/yii-console": "^2.3" + }, + "bin": [ + "bin/yii-db-migration" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "params": "params.php", + "di-console": "di-console.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Db\\Migration\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii DB Migration", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "db", + "migration", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/db-migration/issues?state=open", + "source": "https://github.com/yiisoft/db-migration", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-20T06:57:03+00:00" + }, + { + "name": "yiisoft/db-sqlite", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/db-sqlite.git", + "reference": "b0158543abb378e4524777c8000e3a2180ff6363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/db-sqlite/zipball/b0158543abb378e4524777c8000e3a2180ff6363", + "reference": "b0158543abb378e4524777c8000e3a2180ff6363", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pdo": "*", + "php": "8.1 - 8.5", + "yiisoft/db": "^2.0" + }, + "provide": { + "yiisoft/db-implementation": "1.0.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.89.1", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/aliases": "^2.0", + "yiisoft/psr-dummy-provider": "^1.0", + "yiisoft/test-support": "^3.0", + "yiisoft/var-dumper": "^1.7" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Db\\Sqlite\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "SQLite driver for Yii Database", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "database", + "dbal", + "query-builder", + "sql", + "sqlite", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/db-sqlite/issues?state=open", + "source": "https://github.com/yiisoft/db-sqlite", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-05T14:55:48+00:00" + }, + { + "name": "yiisoft/definitions", + "version": "3.4.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/definitions.git", + "reference": "efba764905b89b549e2b5a7a72f50a79b3d5b0cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/definitions/zipball/efba764905b89b549e2b5a7a72f50a79b3d5b0cc", + "reference": "efba764905b89b549e2b5a7a72f50a79b3d5b0cc", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.69", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.9", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/test-support": "^3.0.1" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Definitions\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "The package provides definition syntax", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "definitions" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/definitions/issues?state=open", + "source": "https://github.com/yiisoft/definitions", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-02T05:29:43+00:00" + }, + { + "name": "yiisoft/di", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/di.git", + "reference": "09545283f29b6311805eca870bf01d2603704c63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/di/zipball/09545283f29b6311805eca870bf01d2603704c63", + "reference": "09545283f29b6311805eca870bf01d2603704c63", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/container": "^1.1 || ^2.0", + "yiisoft/definitions": "^3.0", + "yiisoft/friendly-exception": "^1.1.0" + }, + "provide": { + "psr/container-implementation": "1.0.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "league/container": "^5.1.0", + "maglnet/composer-require-checker": "^4.7.1", + "phpbench/phpbench": "^1.4.1", + "phpunit/phpunit": "^10.5.46", + "rector/rector": "^2.0.17", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/injector": "^1.2.1", + "yiisoft/test-support": "^3.1" + }, + "suggest": { + "phpbench/phpbench": "To run benchmarks.", + "yiisoft/injector": "^1.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Di\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii DI container", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "Autowiring", + "PSR-11", + "container", + "dependency", + "di", + "injection", + "injector" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/di/issues?state=open", + "source": "https://github.com/yiisoft/di", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-01T11:55:03+00:00" + }, + { + "name": "yiisoft/error-handler", + "version": "4.3.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/error-handler.git", + "reference": "562778cf2cab8b09c85249b0d0075f2e12560f53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/error-handler/zipball/562778cf2cab8b09c85249b0d0075f2e12560f53", + "reference": "562778cf2cab8b09c85249b0d0075f2e12560f53", + "shasum": "" + }, + "require": { + "alexkart/curl-builder": "^1.0", + "cebe/markdown": "^1.2", + "ext-dom": "*", + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/container": "^1.0|^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0|^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1|^2.0|^3.0", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/injector": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "httpsoft/http-message": "^1.1.6", + "phpunit/phpunit": "^10.5.51", + "psr/event-dispatcher": "^1.0", + "rector/rector": "^2.1.3", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.13.1", + "yiisoft/di": "^1.4", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di-web": "di-web.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\ErrorHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Error Handling Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "PSR-11", + "error-handler", + "psr-15", + "psr-3", + "psr-7", + "yiisoft" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/error-handler/issues?state=open", + "source": "https://github.com/yiisoft/error-handler", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-01-09T08:26:33+00:00" + }, + { + "name": "yiisoft/event-dispatcher", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/event-dispatcher.git", + "reference": "2b1262a56260030aaac386bf8ef75ec072abc7e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/event-dispatcher/zipball/2b1262a56260030aaac386bf8ef75ec072abc7e3", + "reference": "2b1262a56260030aaac386bf8ef75ec072abc7e3", + "shasum": "" + }, + "require": { + "php": "^8.0", + "psr/event-dispatcher": "1.0.0" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.2", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.14.3", + "roave/infection-static-analysis-plugin": "^1.16", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^4.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\EventDispatcher\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Event Dispatcher", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "event", + "event dispatcher", + "psr-14" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "irc://irc.freenode.net/yii", + "issues": "https://github.com/yiisoft/event-dispatcher/issues?state=open", + "source": "https://github.com/yiisoft/event-dispatcher", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "open_collective" + } + ], + "time": "2022-10-27T12:02:21+00:00" + }, + { + "name": "yiisoft/factory", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/factory.git", + "reference": "c3d8be80dd3f1fc73f42f4293e2ba6b709a44363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/factory/zipball/c3d8be80dd3f1fc73f42f4293e2ba6b709a44363", + "reference": "c3d8be80dd3f1fc73f42f4293e2ba6b709a44363", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/container": "^1.0 || ^2.0", + "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Factory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Factory", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "factory" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/factory/issues?state=open", + "source": "https://github.com/yiisoft/factory", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-02T07:59:18+00:00" + }, + { + "name": "yiisoft/files", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/files.git", + "reference": "465650fd9e4295669f42ab7e9fec2386700540a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/files/zipball/465650fd9e4295669f42ab7e9fec2386700540a7", + "reference": "465650fd9e4295669f42ab7e9fec2386700540a7", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "ext-zlib": "*", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Files\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Helper to manage files and directories", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "files" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/files/issues?state=open", + "source": "https://github.com/yiisoft/files", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-01T06:30:27+00:00" + }, + { + "name": "yiisoft/form", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/form.git", + "reference": "b33b34007ffea2fb412922c9980420c74f93b171" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/form/zipball/b33b34007ffea2fb412922c9980420c74f93b171", + "reference": "b33b34007ffea2fb412922c9980420c74f93b171", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/html": "^3.13 || ^4.0", + "yiisoft/widget": "^2.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.92", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.9.4" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "params": "params.php", + "bootstrap": "bootstrap.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Form\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "The package helps with implementing data entry forms.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "form", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/form/issues?state=open", + "source": "https://github.com/yiisoft/form", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "open_collective" + } + ], + "time": "2026-03-20T07:38:31+00:00" + }, + { + "name": "yiisoft/form-model", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/form-model.git", + "reference": "f89ed3276eadba6d2d997a3d372515cdfd80c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/form-model/zipball/f89ed3276eadba6d2d997a3d372515cdfd80c20d", + "reference": "f89ed3276eadba6d2d997a3d372515cdfd80c20d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/http-message": "^1.0 || ^2.0", + "yiisoft/form": "^1.0", + "yiisoft/html": "^3.3 || ^4.0", + "yiisoft/hydrator": "^1.3", + "yiisoft/strings": "^2.3", + "yiisoft/validator": "^2.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.92", + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.11", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.10", + "yiisoft/di": "^1.3" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\FormModel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Provides a base for form models and helps to fill, validate and display them.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "form", + "model" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/form-model/issues?state=open", + "source": "https://github.com/yiisoft/form-model", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-21T05:47:41+00:00" + }, + { + "name": "yiisoft/friendly-exception", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/friendly-exception.git", + "reference": "c6c36fd60a0b4f1514882d2ce8395f54352ec967" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/friendly-exception/zipball/c6c36fd60a0b4f1514882d2ce8395f54352ec967", + "reference": "c6c36fd60a0b4f1514882d2ce8395f54352ec967", + "shasum": "" + }, + "require": { + "php": "7.4.* || 8.0 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^3.8 || ^4.3", + "phpunit/phpunit": "^9.6.22", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\FriendlyException\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "An interface for friendlier exception", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "error handling", + "exception", + "exceptions", + "friendly" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/friendly-exception/issues?state=open", + "source": "https://github.com/yiisoft/friendly-exception", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-28T14:51:44+00:00" + }, + { + "name": "yiisoft/html", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/html.git", + "reference": "e6f24bc2977114a7800ba4af715f15c147669800" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/html/zipball/e6f24bc2977114a7800ba4af715f15c147669800", + "reference": "e6f24bc2977114a7800ba4af715f15c147669800", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/arrays": "^2.0 || ^3.0", + "yiisoft/json": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.90", + "infection/infection": "^0.27.11 || ^0.32", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.46", + "rector/rector": "^2.0.17", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Html\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Handy library to generate HTML", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "html" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://forum.yiiframework.com/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/html/issues?state=open", + "source": "https://github.com/yiisoft/html", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-18T07:18:34+00:00" + }, + { + "name": "yiisoft/http", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/http.git", + "reference": "8949fa6ab32b943c3e45794fceec220ddfa1e5e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/http/zipball/8949fa6ab32b943c3e45794fceec220ddfa1e5e4", + "reference": "8949fa6ab32b943c3e45794fceec220ddfa1e5e4", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "7.4.* || 8.0 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "maglnet/composer-require-checker": "^3.8 || ^4.3", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Constants and PSR-7 PhpStorm meta for HTTP protocol headers, methods and statuses", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "header", + "http", + "method", + "psr-17", + "psr-7", + "status" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/http/issues?state=open", + "source": "https://github.com/yiisoft/http", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-25T09:08:29+00:00" + }, + { + "name": "yiisoft/hydrator", + "version": "1.6.3", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/hydrator.git", + "reference": "c0f02c2298078a52b64b51eb613eff541e832129" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/hydrator/zipball/c0f02c2298078a52b64b51eb613eff541e832129", + "reference": "c0f02c2298078a52b64b51eb613eff541e832129", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^2.0", + "yiisoft/injector": "^1.1", + "yiisoft/strings": "^2.3" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.48", + "rector/rector": "^2.1.2", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.13.1", + "yiisoft/di": "^1.4", + "yiisoft/dummy-provider": "^1.1.0", + "yiisoft/test-support": "^3.0.2" + }, + "suggest": { + "ext-intl": "Allows using `ToDateTime` parameter attribute" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Hydrator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Create and populate objects with type casting, mapping and dependencies resolving support.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "hydrator" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/hydrator/issues?state=open", + "source": "https://github.com/yiisoft/hydrator", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-16T06:57:38+00:00" + }, + { + "name": "yiisoft/hydrator-validator", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/hydrator-validator.git", + "reference": "ed5c0263fd1ccd729fb096203e854cc509e54d14" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/hydrator-validator/zipball/ed5c0263fd1ccd729fb096203e854cc509e54d14", + "reference": "ed5c0263fd1ccd729fb096203e854cc509e54d14", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "yiisoft/hydrator": "^1.0", + "yiisoft/validator": "^1.0 || ^2.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.11", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.9.6", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Hydrator\\Validator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Validating hydrator with raw data validation support", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "input", + "validation" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/hydrator-validator/issues?state=open", + "source": "https://github.com/yiisoft/hydrator-validator", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-16T13:28:42+00:00" + }, + { + "name": "yiisoft/i18n", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/i18n.git", + "reference": "028fbcee0ea772dab150d0a8f40344a32e639d3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/i18n/zipball/028fbcee0ea772dab150d0a8f40344a32e639d3f", + "reference": "028fbcee0ea772dab150d0a8f40344a32e639d3f", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\I18n\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Internationalization Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "i18n", + "locale" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/i18n/issues?state=open", + "source": "https://github.com/yiisoft/i18n", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-29T15:57:19+00:00" + }, + { + "name": "yiisoft/injector", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/injector.git", + "reference": "d3f718256b734933670ad11143cca724d340fc90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/injector/zipball/d3f718256b734933670ad11143cca724d340fc90", + "reference": "d3f718256b734933670ad11143cca724d340fc90", + "shasum": "" + }, + "require": { + "php": "7.4 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^3.8 || ^4.2", + "phpbench/phpbench": "^1.1", + "phpunit/phpunit": "^9.5", + "psr/container": "^1.0 || ^2.0", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23", + "yiisoft/test-support": "^1.4 || ^3.1" + }, + "suggest": { + "psr/container": "For automatic resolving of dependencies" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Injector\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-11 compatible injector. Executes a callable and makes an instances by injecting dependencies from a given DI container.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "PSR-11", + "dependency injection", + "di", + "injector", + "reflection" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/injector/issues?state=open", + "source": "https://github.com/yiisoft/injector", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-01T11:14:17+00:00" + }, + { + "name": "yiisoft/input-http", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/input-http.git", + "reference": "877fea3374033f5a6af4207036eb7733a635b5b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/input-http/zipball/877fea3374033f5a6af4207036eb7733a635b5b7", + "reference": "877fea3374033f5a6af4207036eb7733a635b5b7", + "shasum": "" + }, + "require": { + "php": "^8.1", + "psr/container": "^1.0|^2.0", + "psr/http-message": "^1.0|^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/arrays": "^3.0", + "yiisoft/hydrator": "^1.0", + "yiisoft/hydrator-validator": "^2.0", + "yiisoft/middleware-dispatcher": "^5.1", + "yiisoft/request-provider": "^1.0", + "yiisoft/validator": "^1.1|^2.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7", + "phpunit/phpunit": "^10.5", + "rector/rector": "^1.0.0", + "roave/infection-static-analysis-plugin": "^1.34", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^5.22", + "yiisoft/di": "^1.2", + "yiisoft/test-support": "^3.0" + }, + "type": "library", + "extra": { + "config-plugin": { + "di-web": "di-web.php", + "params-web": "params-web.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Input\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Maps data from PSR-7 HTTP request to PHP DTO representing user input.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "dto", + "input", + "mapper", + "mapping", + "psr-7", + "request", + "yii3" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/input-http/issues?state=open", + "source": "https://github.com/yiisoft/input-http", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2024-08-06T12:42:23+00:00" + }, + { + "name": "yiisoft/json", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/json.git", + "reference": "6af88ed2c653f4b6cbe3ea9114e4aebc5a463c80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/json/zipball/6af88ed2c653f4b6cbe3ea9114e4aebc5a463c80", + "reference": "6af88ed2c653f4b6cbe3ea9114e4aebc5a463c80", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-simplexml": "*", + "php": "~7.4.0 || 8.0 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "maglnet/composer-require-checker": "^3.8 || ^4.2", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.8", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Json\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii JSON encoding and decoding", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "json" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/json/issues?state=open", + "source": "https://github.com/yiisoft/json", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-21T19:39:36+00:00" + }, + { + "name": "yiisoft/log", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/log.git", + "reference": "e98e881d7ff0f00521a713a1852cbbffbaf279d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/log/zipball/e98e881d7ff0f00521a713a1852cbbffbaf279d5", + "reference": "e98e881d7ff0f00521a713a1852cbbffbaf279d5", + "shasum": "" + }, + "require": { + "php": "^8.0", + "psr/log": "^2.0 || ^3.0", + "yiisoft/var-dumper": "^1.0" + }, + "conflict": { + "ext-psr": "*" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.93", + "phpbench/phpbench": "^1.0", + "phpunit/phpunit": "^9.6.23", + "rector/rector": "^2.0.17", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.12", + "yiisoft/code-style": "^1.0" + }, + "suggest": { + "yiisoft/log-target-db": "Allows writing log messages to the database", + "yiisoft/log-target-email": "Allows sending log messages by email", + "yiisoft/log-target-file": "Allows writing log messages to the files", + "yiisoft/log-target-syslog": "Allows writing log messages to the Syslog" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "events-web": "events-web.php", + "events-console": "events-console.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Logging Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "framework", + "log", + "logger", + "psr-3", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/log/issues?state=open", + "source": "https://github.com/yiisoft/log", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-22T16:33:56+00:00" + }, + { + "name": "yiisoft/log-target-file", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/log-target-file.git", + "reference": "24d51c88a362c3c60adafa884b959f0423a208da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/log-target-file/zipball/24d51c88a362c3c60adafa884b959f0423a208da", + "reference": "24d51c88a362c3c60adafa884b959f0423a208da", + "shasum": "" + }, + "require": { + "ext-zlib": "*", + "php": "^8.0", + "yiisoft/files": "^1.0|^2.0", + "yiisoft/log": "^2.2" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.2", + "phpunit/phpunit": "^9.5", + "rector/rector": "^2.0", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^4.30|^5.24", + "yiisoft/aliases": "^3.0", + "yiisoft/di": "^1.0" + }, + "suggest": { + "ext-zlib": "Enabling gzip compression of rotated files." + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Log\\Target\\File\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Logging Library - File Target", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "framework", + "log", + "logger", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/log-target-file/issues", + "source": "https://github.com/yiisoft/log-target-file", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T11:57:57+00:00" + }, + { + "name": "yiisoft/middleware-dispatcher", + "version": "5.4.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/middleware-dispatcher.git", + "reference": "26b7811d442c2d3bf5ab4d1c8f577750a6c0ed30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/middleware-dispatcher/zipball/26b7811d442c2d3bf5ab4d1c8f577750a6c0ed30", + "reference": "26b7811d442c2d3bf5ab4d1c8f577750a6c0ed30", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "psr/event-dispatcher": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/definitions": "^2.0 || ^3.0", + "yiisoft/friendly-exception": "^1.1", + "yiisoft/injector": "^1.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^10.5.48", + "rector/rector": "^2.2.14", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.13", + "yiisoft/test-support": "^3.0.2", + "yiisoft/yii-debug": "dev-master" + }, + "type": "library", + "extra": { + "config-plugin": { + "events-web": "events-web.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Middleware\\Dispatcher\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-15 middleware dispatcher", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "dispatcher", + "middleware" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/middleware-dispatcher/issues?state=open", + "source": "https://github.com/yiisoft/middleware-dispatcher", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T03:30:05+00:00" + }, + { + "name": "yiisoft/network-utilities", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/network-utilities.git", + "reference": "5efc2e4a2e92acaa01c13fcc0cbc9cc3cd633b37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/network-utilities/zipball/5efc2e4a2e92acaa01c13fcc0cbc9cc3cd633b37", + "reference": "5efc2e4a2e92acaa01c13fcc0cbc9cc3cd633b37", + "shasum": "" + }, + "require": { + "php": "7.4.* || 8.0 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^3.8 || ^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\NetworkUtilities\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Network related utilities", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "IP", + "dns", + "mask", + "network" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/network-utilities/issues?state=open", + "source": "https://github.com/yiisoft/network-utilities", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-28T08:12:08+00:00" + }, + { + "name": "yiisoft/psr-emitter", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/psr-emitter.git", + "reference": "d09a29d1feec91596491973757f6a112991e29b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/psr-emitter/zipball/d09a29d1feec91596491973757f6a112991e29b3", + "reference": "d09a29d1feec91596491973757f6a112991e29b3", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/http-message": "^2.0", + "yiisoft/friendly-exception": "^1.1" + }, + "require-dev": { + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.46", + "psr/http-server-middleware": "^1.0.2", + "rector/rector": "^2.0.16", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.10.3", + "xepozz/internal-mocker": "^1.4.1" + }, + "suggest": { + "psr/http-server-middleware": "To use emitter as middleware." + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\PsrEmitter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-7 HTTP response emitter", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "emitter", + "http", + "psr-7" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/psr-emitter/issues?state=open", + "source": "https://github.com/yiisoft/psr-emitter", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-20T05:12:53+00:00" + }, + { + "name": "yiisoft/rbac", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/rbac.git", + "reference": "229a47e0af4ede19dfe6da2220af7cabee724dbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/rbac/zipball/229a47e0af4ede19dfe6da2220af7cabee724dbf", + "reference": "229a47e0af4ede19dfe6da2220af7cabee724dbf", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/access": "^2.0", + "yiisoft/friendly-exception": "^1.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.91", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "psr/clock": "^1.0", + "rector/rector": "^2.0.10", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.9.2", + "yiisoft/di": "^1.3" + }, + "suggest": { + "psr/clock": "For using custom clock", + "yiisoft/rbac-cycle-db": "For using Cycle as a storage", + "yiisoft/rbac-db": "For using Yii Database as a storage", + "yiisoft/rbac-php": "For using PHP files as a storage", + "yiisoft/rbac-rules-container": "To create rules via Yii Factory" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Rbac\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Role-Based Access Control", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "rbac", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/rbac/issues?state=open", + "source": "https://github.com/yiisoft/rbac", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-19T12:14:21+00:00" + }, + { + "name": "yiisoft/rbac-db", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/rbac-db.git", + "reference": "a8dab91a5e35f95f53c98c4e6a3c7074456189c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/rbac-db/zipball/a8dab91a5e35f95f53c98c4e6a3c7074456189c0", + "reference": "a8dab91a5e35f95f53c98c4e6a3c7074456189c0", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": "8.1 - 8.5", + "yiisoft/db": "^2.0", + "yiisoft/db-migration": "^2.0", + "yiisoft/friendly-exception": "^1.1", + "yiisoft/rbac": "^2.1" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "psr/clock": "^1.0", + "rector/rector": "^2.0.11", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.10", + "yiisoft/cache": "^3.0", + "yiisoft/db-sqlite": "^2.0" + }, + "suggest": { + "yiisoft/db-migration": "For automating schema migration", + "yiisoft/db-mssql": "For using with Microsoft SQL Server", + "yiisoft/db-mysql": "For using with MySQL", + "yiisoft/db-oracle": "For using with Oracle", + "yiisoft/db-pgsql": "For using with PosgtgreSQL", + "yiisoft/db-sqlite": "For using with SQLite" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Rbac\\Db\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii RBAC Database storage", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "db", + "rbac", + "storage", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/rbac-db/issues?state=open", + "source": "https://github.com/yiisoft/rbac-db", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-19T12:18:59+00:00" + }, + { + "name": "yiisoft/rbac-php", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/rbac-php.git", + "reference": "02aa4e1cc08ca0d1ce9cdf67da8e6690d1059d3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/rbac-php/zipball/02aa4e1cc08ca0d1ce9cdf67da8e6690d1059d3b", + "reference": "02aa4e1cc08ca0d1ce9cdf67da8e6690d1059d3b", + "shasum": "" + }, + "require": { + "php": "^8.1", + "yiisoft/rbac": "^2.0", + "yiisoft/var-dumper": "^1.7" + }, + "require-dev": { + "ext-uopz": "*", + "maglnet/composer-require-checker": "^4.3", + "phpunit/phpunit": "^10.5.2", + "psr/log": "^1.1.3", + "rector/rector": "^1.0.0", + "roave/infection-static-analysis-plugin": "^1.18", + "slope-it/clock-mock": "0.4.0", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^4.30|^5.17", + "yiisoft/files": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Rbac\\Php\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii RBAC PHP File Storage", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "rbac", + "storage", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "irc://irc.freenode.net/yii", + "issues": "https://github.com/yiisoft/rbac/issues", + "source": "https://github.com/yiisoft/rbac", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2024-03-07T10:52:17+00:00" + }, + { + "name": "yiisoft/request-body-parser", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/request-body-parser.git", + "reference": "923c67596b05aa98dc0ed911737c6ab18da7459f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/request-body-parser/zipball/923c67596b05aa98dc0ed911737c6ab18da7459f", + "reference": "923c67596b05aa98dc0ed911737c6ab18da7459f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.1", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-message-implementation": "1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2" + }, + "require-dev": { + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.55", + "rector/rector": "^2.1", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.13.1", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Request\\Body\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Middleware for parsing various data formats", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "body", + "middleware", + "parser", + "yii3" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/request-body-parser/issues?state=open", + "source": "https://github.com/yiisoft/request-body-parser", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-21T05:24:00+00:00" + }, + { + "name": "yiisoft/request-provider", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/request-provider.git", + "reference": "6676b0e4d213fc987f01bcede8053b2be4ce2c63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/request-provider/zipball/6676b0e4d213fc987f01bcede8053b2be4ce2c63", + "reference": "6676b0e4d213fc987f01bcede8053b2be4ce2c63", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.93", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "roave/infection-static-analysis-plugin": "^1.35", + "vimeo/psalm": "^5.26.1 || ^6.8.9", + "yiisoft/code-style": "^1.0", + "yiisoft/di": "^1.3" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di-web": "di-web.php", + "events-web": "events-web.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\RequestProvider\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-7 request provider", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "http", + "provider", + "psr", + "request", + "yii3" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/request-provider/issues?state=open", + "source": "https://github.com/yiisoft/request-provider", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-01-29T14:03:21+00:00" + }, + { + "name": "yiisoft/router", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/router.git", + "reference": "dff8d252e87eb99e415fbc59439546d3ea432fa9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/router/zipball/dff8d252e87eb99e415fbc59439546d3ea432fa9", + "reference": "dff8d252e87eb99e415fbc59439546d3ea432fa9", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/event-dispatcher": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/middleware-dispatcher": "^5.0", + "yiisoft/router-implementation": "1.0.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^10.5.45", + "psr/container": "^1.1 || ^2.0.2", + "rector/rector": "^2.0.9", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.8.6", + "yiisoft/di": "^1.3", + "yiisoft/dummy-provider": "^1.0.1", + "yiisoft/hydrator": "^1.5", + "yiisoft/test-support": "^3.0.1", + "yiisoft/yii-debug": "dev-master" + }, + "suggest": { + "yiisoft/hydrator": "Needed to use `RouteArgument` attribute", + "yiisoft/router-fastroute": "Router implementation based on nikic/FastRoute" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Router\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii router", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "middleware", + "router", + "web" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/router/issues?state=open", + "source": "https://github.com/yiisoft/router", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T10:19:16+00:00" + }, + { + "name": "yiisoft/router-fastroute", + "version": "4.0.3", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/router-fastroute.git", + "reference": "13f97b5c7934aacaece3318ab947a12fcbe532f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/router-fastroute/zipball/13f97b5c7934aacaece3318ab947a12fcbe532f3", + "reference": "13f97b5c7934aacaece3318ab947a12fcbe532f3", + "shasum": "" + }, + "require": { + "nikic/fast-route": "^1.3", + "php": "8.1 - 8.5", + "psr/http-message": "^1.0 || ^2.0", + "psr/simple-cache": "^2.0 || ^3.0", + "yiisoft/http": "^1.2", + "yiisoft/router": "^4" + }, + "provide": { + "yiisoft/router-implementation": "1.0.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^10.5.55", + "psr/container": "^2.0.2", + "rector/rector": "^2.1.7", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.8.6", + "yiisoft/di": "^1.4", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Router\\FastRoute\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii router FastRoute adapter", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "FastRoute", + "router" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/router-fastroute/issues?state=open", + "source": "https://github.com/yiisoft/router-fastroute", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-13T11:58:56+00:00" + }, + { + "name": "yiisoft/security", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/security.git", + "reference": "8d445e53ab784374a7333ed3b66ad2ada084c9fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/security/zipball/8d445e53ab784374a7333ed3b66ad2ada084c9fe", + "reference": "8d445e53ab784374a7333ed3b66ad2ada084c9fe", + "shasum": "" + }, + "require": { + "ext-hash": "*", + "ext-openssl": "*", + "php": "8.1 - 8.5", + "yiisoft/strings": "^2.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.9", + "spatie/phpunit-watcher": "^1.24" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Security\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Security utilities", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "MAC", + "decryption", + "encryption", + "hash", + "password", + "random", + "security", + "signature", + "token masking" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/security/issues?state=open", + "source": "https://github.com/yiisoft/security", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-25T09:24:59+00:00" + }, + { + "name": "yiisoft/session", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/session.git", + "reference": "755e15352181995b69a4f293a06a128e0569915d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/session/zipball/755e15352181995b69a4f293a06a128e0569915d", + "reference": "755e15352181995b69a4f293a06a128e0569915d", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-message-implementation": "1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/cookies": "^1.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.4", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.6 || ^6.8.8", + "yiisoft/di": "^1.2.1" + }, + "suggest": { + "ext-session": "Allows using native PHP sessions" + }, + "type": "library", + "extra": { + "config-plugin": { + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Session\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A session service, PSR-15 session middleware, and a flash message service which helps use one-time messages.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "flash", + "middleware", + "psr-15", + "session" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/session/issues?state=open", + "source": "https://github.com/yiisoft/session", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-17T13:15:55+00:00" + }, + { + "name": "yiisoft/strings", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/strings.git", + "reference": "9bc7fea56374619cccd4587848029fe97f98bb33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/strings/zipball/9bc7fea56374619cccd4587848029fe97f98bb33", + "reference": "9bc7fea56374619cccd4587848029fe97f98bb33", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "maglnet/composer-require-checker": "^4.7.1", + "phpbench/phpbench": "^1.4.1", + "phpunit/phpunit": "^10.5.48", + "rector/rector": "^2.1.2", + "spatie/phpunit-watcher": "^1.24" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Strings\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Strings Helper", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "helper", + "string", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/strings/issues?state=open", + "source": "https://github.com/yiisoft/strings", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-11-23T18:00:58+00:00" + }, + { + "name": "yiisoft/translator", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/translator.git", + "reference": "62c64c9009a570597cc31dd42ff951d74049a60b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/translator/zipball/62c64c9009a570597cc31dd42ff951d74049a60b", + "reference": "62c64c9009a570597cc31dd42ff951d74049a60b", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/event-dispatcher": "1.0.0", + "yiisoft/files": "^1.0 || ^2.0", + "yiisoft/i18n": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.29", + "rector/rector": "^2.1.7", + "spatie/phpunit-watcher": "^1.23.6", + "yiisoft/di": "^1.2.1" + }, + "suggest": { + "ext-intl": "Allows using intl message formatter", + "ext-tokenizer": "Allows using message extraction", + "yiisoft/event-dispatcher": "To listen for events about missing categories and messages" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Translator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Message Translator", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "i18n", + "internationalization", + "translation" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/translator/issues?state=open", + "source": "https://github.com/yiisoft/translator", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-06T05:18:44+00:00" + }, + { + "name": "yiisoft/user", + "version": "2.3.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/user.git", + "reference": "f982e9faa3acac8a04299968b1c74e5123e4cc14" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/user/zipball/f982e9faa3acac8a04299968b1c74e5123e4cc14", + "reference": "f982e9faa3acac8a04299968b1c74e5123e4cc14", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/event-dispatcher": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "yiisoft/access": "^2.0", + "yiisoft/auth": "^2.0 || ^3.0", + "yiisoft/cookies": "^1.2", + "yiisoft/http": "^1.2", + "yiisoft/session": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.10", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.8.8", + "yiisoft/di": "^1.3", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "config-plugin": { + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\User\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Convenient user identity management and access checking", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "user", + "yiisoft" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/user/issues?state=open", + "source": "https://github.com/yiisoft/user", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-23T06:15:18+00:00" + }, + { + "name": "yiisoft/validator", + "version": "2.5.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/validator.git", + "reference": "0679b3d2f33acf1b8d0cbe329d6e305e18769fbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/validator/zipball/0679b3d2f33acf1b8d0cbe329d6e305e18769fbb", + "reference": "0679b3d2f33acf1b8d0cbe329d6e305e18769fbb", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "psr/http-message": "^1.0 || ^2.0", + "yiisoft/arrays": "^2.1 || ^3.0", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/network-utilities": "^1.2", + "yiisoft/strings": "^2.6", + "yiisoft/translator": "^2.1 || ^3.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.91", + "jetbrains/phpstorm-attributes": "^1.2", + "maglnet/composer-require-checker": "^4.7.1", + "phpbench/phpbench": "^1.4.1", + "phpunit/phpunit": "^10.5.46", + "rector/rector": "^2.0.16", + "spatie/phpunit-watcher": "^1.24", + "yiisoft/di": "^1.3", + "yiisoft/test-support": "^3.0.2", + "yiisoft/translator-message-php": "^1.1.1", + "yiisoft/yii-debug": "dev-master" + }, + "suggest": { + "ext-fileinfo": "To use image rule", + "ext-intl": "Allows using date rules and IDN validation for emails", + "yiisoft/di": "To create rule handlers via Yii DI" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Validator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Validator", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "validation", + "validator" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/validator/issues?state=open", + "source": "https://github.com/yiisoft/validator", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-12T14:36:09+00:00" + }, + { + "name": "yiisoft/var-dumper", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/var-dumper.git", + "reference": "0860637f99fddfbeb98976bcc716b2aabc94ff85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/var-dumper/zipball/0860637f99fddfbeb98976bcc716b2aabc94ff85", + "reference": "0860637f99fddfbeb98976bcc716b2aabc94ff85", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "php": "8.0 - 8.5", + "yiisoft/arrays": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.10", + "spatie/phpunit-watcher": "^1.23.6" + }, + "suggest": { + "ext-sockets": "Send dumps to a server through UDP/TCP protocols" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Yiisoft\\VarDumper\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Enhances functionality of var_dump() and var_export(). It is dealing with recursive references, may highlight syntax and export closures.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "framework", + "helper", + "var-dumper", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/var-dumper/issues?state=open", + "source": "https://github.com/yiisoft/var-dumper", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-01T13:24:08+00:00" + }, + { + "name": "yiisoft/view", + "version": "12.2.4", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/view.git", + "reference": "eaf52e6ba92ce6b622a6718bda295f8383964e12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/view/zipball/eaf52e6ba92ce6b622a6718bda295f8383964e12", + "reference": "eaf52e6ba92ce6b622a6718bda295f8383964e12", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "yiisoft/arrays": "^2.0 || ^3.0", + "yiisoft/cache": "^1.0 || ^2.0 || ^3.0", + "yiisoft/files": "^1.0 || ^2.0", + "yiisoft/html": "^2.5 || ^3.0 || ^4.0", + "yiisoft/json": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "friendsofphp/php-cs-fixer": "^3.93", + "maglnet/composer-require-checker": "^4.7.1", + "phpbench/phpbench": "^1.4.3", + "phpunit/phpunit": "^10.5.60", + "rector/rector": "^2.3.4", + "spatie/phpunit-watcher": "^1.24.4", + "yiisoft/aliases": "^3.1.1", + "yiisoft/code-style": "^1.0", + "yiisoft/di": "^1.4.1", + "yiisoft/psr-dummy-provider": "^1.0.2", + "yiisoft/test-support": "^3.1.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di": "di.php", + "di-web": "di-web.php", + "params": "params.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\View\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii View Rendering Library", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "view", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/view/issues?state=open", + "source": "https://github.com/yiisoft/view", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-18T10:35:05+00:00" + }, + { + "name": "yiisoft/widget", + "version": "2.2.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/widget.git", + "reference": "a3a88b7b5a0ced16a8354e4a915226301bae76dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/widget/zipball/a3a88b7b5a0ced16a8354e4a915226301bae76dc", + "reference": "a3a88b7b5a0ced16a8354e4a915226301bae76dc", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/container": "^1.0 || ^2.0", + "yiisoft/definitions": "^3.1", + "yiisoft/factory": "^1.2", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/html": "^2.0 || ^3.0 || ^4.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.2.14", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.9.1", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "config-plugin": { + "params": "params.php", + "widgets": [], + "bootstrap": "bootstrap.php", + "widgets-themes": [] + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Widget\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Widget", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "widgets", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/widget/issues?state=open", + "source": "https://github.com/yiisoft/widget", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-18T10:37:07+00:00" + }, + { + "name": "yiisoft/yii-console", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-console.git", + "reference": "d03e618c542b8908fce91be7f34969040f548506" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-console/zipball/d03e618c542b8908fce91be7f34969040f548506", + "reference": "d03e618c542b8908fce91be7f34969040f548506", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/container": "^1.0 || ^2.0", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/event-dispatcher-contracts": "^2.2 || ^3.0", + "yiisoft/friendly-exception": "^1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.11", + "yiisoft/config": "^1.5", + "yiisoft/di": "^1.2.1", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di-console": "di-console.php", + "events-console": "events-console.php", + "params-console": "params-console.php" + }, + "config-plugin-options": { + "merge-plan-file": "../tests/environment/.merge-plan.php", + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Console\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Symfony console wrapper with additional features", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "console", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-console/issues?state=open", + "source": "https://github.com/yiisoft/yii-console", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-20T05:15:30+00:00" + }, + { + "name": "yiisoft/yii-dataview", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-dataview.git", + "reference": "832f14490a021d240b7c7d0ed476063548176cf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-dataview/zipball/832f14490a021d240b7c7d0ed476063548176cf0", + "reference": "832f14490a021d240b7c7d0ed476063548176cf0", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "yiisoft/arrays": "^3.1", + "yiisoft/data": "^2.0", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/html": "^3.13 || ^4.0", + "yiisoft/injector": "^1.2", + "yiisoft/router": "^4.0", + "yiisoft/translator": "^3.2", + "yiisoft/validator": "^2.0", + "yiisoft/view": "^12.0.0", + "yiisoft/widget": "^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.91", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.58", + "rector/rector": "^2.1.7", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.12", + "yiisoft/di": "^1.4", + "yiisoft/event-dispatcher": "^1.1", + "yiisoft/log": "^2.1.1", + "yiisoft/router-fastroute": "^4.0.2", + "yiisoft/test-support": "^3.0.2", + "yiisoft/translator-message-php": "^1.1.1" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "params": "params.php", + "widgets-themes": "widgets-themes.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\DataView\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii data displaying widgets", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "data", + "grid", + "list", + "view", + "widget", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-dataview/issues?state=open", + "source": "https://github.com/yiisoft/yii-dataview", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-21T14:40:58+00:00" + }, + { + "name": "yiisoft/yii-event", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-event.git", + "reference": "ad5fbcf742d5e9defbc3d13f396a6b879e70e2b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-event/zipball/ad5fbcf742d5e9defbc3d13f396a6b879e70e2b6", + "reference": "ad5fbcf742d5e9defbc3d13f396a6b879e70e2b6", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "yiisoft/event-dispatcher": "^1.0", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/injector": "^1.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.2.14", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.9.5", + "yiisoft/config": "^1.6", + "yiisoft/di": "^1.3", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "config-plugin": { + "di": "di.php", + "di-web": "di-web.php", + "di-console": "di-console.php", + "events-web": [], + "params-web": "params-web.php", + "events-console": [], + "params-console": "params-console.php" + }, + "config-plugin-options": { + "merge-plan-file": "../tests/environment/.merge-plan.php", + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Event\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii Event", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "event", + "yii3" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-event/issues?state=open", + "source": "https://github.com/yiisoft/yii-event", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-18T20:53:21+00:00" + }, + { + "name": "yiisoft/yii-http", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-http.git", + "reference": "c2e7fb9cee4a0f91e8940ee1759ce11eaa479314" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-http/zipball/c2e7fb9cee4a0f91e8940ee1759ce11eaa479314", + "reference": "c2e7fb9cee4a0f91e8940ee1759ce11eaa479314", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "yiisoft/http": "^1.2", + "yiisoft/middleware-dispatcher": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.53", + "psr/event-dispatcher": "^1.0", + "rector/rector": "^2.1.6", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24.0", + "vimeo/psalm": "^5.26.1 || ^6.13.1", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii HTTP Application", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "application", + "http", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-http/issues?state=open", + "source": "https://github.com/yiisoft/yii-http", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-18T21:00:08+00:00" + }, + { + "name": "yiisoft/yii-runner", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-runner.git", + "reference": "8412249e76e58a71903df17b06e69900c705af7b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-runner/zipball/8412249e76e58a71903df17b06e69900c705af7b", + "reference": "8412249e76e58a71903df17b06e69900c705af7b", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "psr/container": "^1.0 || ^2.0", + "yiisoft/config": "^1.1", + "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0", + "yiisoft/di": "^1.0", + "yiisoft/yii-event": "^2.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^4.4", + "phpunit/phpunit": "^9.6.22", + "rector/rector": "^2.0.11", + "roave/infection-static-analysis-plugin": "^1.25", + "spatie/phpunit-watcher": "^1.23.6", + "vimeo/psalm": "^4.30 || ^5.26.1 || ^6.10", + "yiisoft/test-support": "^3.0.2" + }, + "suggest": { + "yiisoft/yii-runner-console": "Allows to run console application", + "yiisoft/yii-runner-http": "Allows to run HTTP application", + "yiisoft/yii-runner-roadrunner": "Allows to run HTTP application for RoadRunner" + }, + "type": "library", + "extra": { + "config-plugin-options": { + "build-merge-plan": false + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Runner\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Yii application runner", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "runner", + "yii3" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-runner/issues?state=open", + "source": "https://github.com/yiisoft/yii-runner", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-19T12:23:49+00:00" + }, + { + "name": "yiisoft/yii-runner-console", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-runner-console.git", + "reference": "16ca4daa1c02ef4c9e2d0db4cf30a194467c6a34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-runner-console/zipball/16ca4daa1c02ef4c9e2d0db4cf30a194467c6a34", + "reference": "16ca4daa1c02ef4c9e2d0db4cf30a194467c6a34", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5", + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "yiisoft/config": "^1.1", + "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0", + "yiisoft/di": "^1.0", + "yiisoft/yii-console": "^2.0", + "yiisoft/yii-runner": "^2.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.3", + "codeception/codeception": "^5.1.2", + "codeception/module-cli": "^2.0.1", + "rector/rector": "^2.0.11" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin-options": { + "build-merge-plan": false + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Runner\\Console\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Console application runner", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "console", + "runner", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-runner-console/issues?state=open", + "source": "https://github.com/yiisoft/yii-runner-console", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-20T07:01:24+00:00" + }, + { + "name": "yiisoft/yii-runner-http", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-runner-http.git", + "reference": "f80669e1ff9b87ab6f6f4cec926d11dc1d68e7d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-runner-http/zipball/f80669e1ff9b87ab6f6f4cec926d11dc1d68e7d6", + "reference": "f80669e1ff9b87ab6f6f4cec926d11dc1d68e7d6", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/log": "^3.0", + "yiisoft/config": "^1.1", + "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0", + "yiisoft/di": "^1.0", + "yiisoft/error-handler": "^4.0", + "yiisoft/friendly-exception": "^1.1", + "yiisoft/http": "^1.2", + "yiisoft/psr-emitter": "^1.0", + "yiisoft/yii-http": "^1.0", + "yiisoft/yii-runner": "^2.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "httpsoft/http-message": "^1.1.6", + "phpunit/phpunit": "^10.5.46", + "rector/rector": "^2.0.18", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1 || ^6.12", + "yiisoft/middleware-dispatcher": "^5.2", + "yiisoft/test-support": "^3.0.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin-options": { + "build-merge-plan": false + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\Runner\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "HTTP application runner", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "http", + "runner", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-runner-http/issues?state=open", + "source": "https://github.com/yiisoft/yii-runner-http", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2025-12-20T07:04:15+00:00" + }, + { + "name": "yiisoft/yii-view-renderer", + "version": "7.4.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii-view-renderer.git", + "reference": "12d788cf635657138513ea314ecca0078dfb127f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii-view-renderer/zipball/12d788cf635657138513ea314ecca0078dfb127f", + "reference": "12d788cf635657138513ea314ecca0078dfb127f", + "shasum": "" + }, + "require": { + "php": "8.1 - 8.5", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.1", + "psr/http-message": "^1.1 | ^2.0", + "yiisoft/aliases": "^2.0 || ^3.0", + "yiisoft/csrf": "^1.2 || ^2.0", + "yiisoft/data-response": "^2.2", + "yiisoft/friendly-exception": "^1.0", + "yiisoft/html": "^2.5 || ^3.0 || ^4.0", + "yiisoft/strings": "^2.0", + "yiisoft/view": "^12" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.9.1", + "friendsofphp/php-cs-fixer": "^3.94", + "httpsoft/http-message": "^1.1.6", + "nyholm/psr7": "^1.8.2", + "phpunit/phpunit": "^10.5.63", + "rector/rector": "^2.3.8", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24.4", + "vimeo/psalm": "^5.26.1 || ^6.15.1", + "yiisoft/code-style": "^1.0", + "yiisoft/di": "^1.4.1", + "yiisoft/psr-dummy-provider": "^1.0.2", + "yiisoft/test-support": "^3.2.0", + "yiisoft/yii-debug": "dev-master" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true, + "target-directory": "tools" + }, + "config-plugin": { + "di-web": "di-web.php", + "params": "params.php", + "events-web": "events-web.php" + }, + "config-plugin-options": { + "source-directory": "config" + } + }, + "autoload": { + "psr-4": { + "Yiisoft\\Yii\\View\\Renderer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-7 compatible view renderer", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "renderer", + "view", + "yii" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "ircs://irc.libera.chat:6697/yii", + "issues": "https://github.com/yiisoft/yii-view-renderer/issues?state=open", + "source": "https://github.com/yiisoft/yii-view-renderer", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/sponsors/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "opencollective" + } + ], + "time": "2026-03-18T13:13:58+00:00" + } + ], + "packages-dev": [ + { + "name": "amphp/amp", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-08-27T21:42:00+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T17:10:27+00:00" + }, + { + "name": "amphp/cache", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Cache\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", + "support": { + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" + }, + { + "name": "amphp/dns", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/dns.git", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/process": "^2", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "ext-json": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Dns\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", + "keywords": [ + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" + ], + "support": { + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-01-19T15:43:40+00:00" + }, + { + "name": "amphp/parallel", + "version": "v2.3.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/parallel.git", + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parallel/zipball/296b521137a54d3a02425b464e5aee4c93db2c60", + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/pipeline": "^1", + "amphp/process": "^2", + "amphp/serialization": "^1", + "amphp/socket": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "files": [ + "src/Context/functions.php", + "src/Context/Internal/functions.php", + "src/Ipc/functions.php", + "src/Worker/functions.php" + ], + "psr-4": { + "Amp\\Parallel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", + "keywords": [ + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" + ], + "support": { + "issues": "https://github.com/amphp/parallel/issues", + "source": "https://github.com/amphp/parallel/tree/v2.3.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-11-15T06:23:42+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "7b52598c2e9105ebcddf247fc523161581930367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", + "reference": "7b52598c2e9105ebcddf247fc523161581930367", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T16:33:53+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-08-03T19:31:26+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.16.1", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "e26037937dfd48528746764dd870bc5d0836665f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/e26037937dfd48528746764dd870bc5d0836665f", + "reference": "e26037937dfd48528746764dd870bc5d0836665f", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "php": ">=8.1 <8.6" + }, + "require-dev": { + "cucumber/gherkin-monorepo": "dev-gherkin-v37.0.0", + "friendsofphp/php-cs-fixer": "^3.77", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Gherkin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "https://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP", + "homepage": "https://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "support": { + "issues": "https://github.com/Behat/Gherkin/issues", + "source": "https://github.com/Behat/Gherkin/tree/v4.16.1" + }, + "funding": [ + { + "url": "https://github.com/acoulton", + "type": "github" + }, + { + "url": "https://github.com/carlos-granados", + "type": "github" + }, + { + "url": "https://github.com/stof", + "type": "github" + } + ], + "time": "2025-12-08T16:12:58+00:00" + }, + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "codeception/c3", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/c3.git", + "reference": "e23298a1cd5e7745973ea26a53572a3d9b013439" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/c3/zipball/e23298a1cd5e7745973ea26a53572a3d9b013439", + "reference": "e23298a1cd5e7745973ea26a53572a3d9b013439", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.5.0" + }, + "require-dev": { + "composer/composer": "^1.0 || ^2.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Codeception\\c3\\Installer" + }, + "autoload": { + "psr-4": { + "Codeception\\c3\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tiger Seo", + "email": "tiger.seo@gmail.com" + }, + { + "name": "Michael Bodnarchuk", + "email": "davert.php@codegyre.com", + "homepage": "http://codegyre.com" + } + ], + "description": "CodeCoverage collector for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "code coverage", + "codecoverage" + ], + "support": { + "issues": "https://github.com/Codeception/c3/issues", + "source": "https://github.com/Codeception/c3/tree/2.9.0" + }, + "time": "2023-10-15T17:57:07+00:00" + }, + { + "name": "codeception/codeception", + "version": "5.3.5", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Codeception.git", + "reference": "83c2986ec2abe594cee2f706d9ec7aca2878fbe0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/83c2986ec2abe594cee2f706d9ec7aca2878fbe0", + "reference": "83c2986ec2abe594cee2f706d9ec7aca2878fbe0", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.12", + "codeception/lib-asserts": "^2.2 | ^3.0.1", + "codeception/stub": "^4.1", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.2", + "phpunit/php-code-coverage": "^9.2 | ^10.0 | ^11.0 | ^12.0 | ^13.0", + "phpunit/php-text-template": "^2.0 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "phpunit/php-timer": "^5.0.3 | ^6.0 | ^7.0 | ^8.0 | ^9.0", + "phpunit/phpunit": "^9.5.20 | ^10.0 | ^11.0 | ^12.0 | ^13.0", + "psy/psysh": "^0.11.2 | ^0.12", + "sebastian/comparator": "^4.0.5 | ^5.0 | ^6.0 | ^7.0 | ^8.0", + "sebastian/diff": "^4.0.3 | ^5.0 | ^6.0 | ^7.0 | ^8.0", + "symfony/console": ">=5.4.24 <9.0", + "symfony/css-selector": ">=5.4.24 <9.0", + "symfony/event-dispatcher": ">=5.4.24 <9.0", + "symfony/finder": ">=5.4.24 <9.0", + "symfony/var-dumper": ">=5.4.24 <9.0", + "symfony/yaml": ">=5.4.24 <9.0" + }, + "conflict": { + "codeception/lib-innerbrowser": "<3.1.3", + "codeception/module-filesystem": "<3.0", + "codeception/module-phpbrowser": "<2.5" + }, + "replace": { + "codeception/phpunit-wrapper": "*" + }, + "require-dev": { + "codeception/lib-innerbrowser": "*@dev", + "codeception/lib-web": "*@dev", + "codeception/module-asserts": "dev-master", + "codeception/module-cli": "*@dev", + "codeception/module-db": "*@dev", + "codeception/module-filesystem": "*@dev", + "codeception/module-phpbrowser": "*@dev", + "codeception/module-webdriver": "*@dev", + "codeception/util-universalframework": "*@dev", + "doctrine/orm": "^3.3", + "ext-simplexml": "*", + "jetbrains/phpstorm-attributes": "^1.0", + "laravel-zero/phar-updater": "^1.4", + "php-webdriver/webdriver": "^1.15", + "stecman/symfony-console-completion": "^0.14 || ^0.15", + "symfony/dotenv": ">=5.4.24 <9.0", + "symfony/error-handler": ">=5.4.24 <9.0", + "symfony/process": ">=5.4.24 <9.0", + "vlucas/phpdotenv": "^5.1" + }, + "suggest": { + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "ext-simplexml": "For loading params from XML files", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/dotenv": "For loading params from .env files", + "symfony/phpunit-bridge": "For phpunit-bridge support", + "vlucas/phpdotenv": "For loading params from .env files" + }, + "bin": [ + "codecept" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.3.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Codeception\\": "src/Codeception", + "Codeception\\Extension\\": "ext" + }, + "classmap": [ + "src/PHPUnit/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert.ua@gmail.com", + "homepage": "https://codeception.com" + } + ], + "description": "All-in-one PHP Testing Framework", + "homepage": "https://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "support": { + "issues": "https://github.com/Codeception/Codeception/issues", + "source": "https://github.com/Codeception/Codeception/tree/5.3.5" + }, + "funding": [ + { + "url": "https://opencollective.com/codeception", + "type": "open_collective" + } + ], + "time": "2026-02-18T06:18:00+00:00" + }, + { + "name": "codeception/lib-asserts", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-asserts.git", + "reference": "f161e5d3a9e5ae573ca01cfb3b5601ff5303df03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/f161e5d3a9e5ae573ca01cfb3b5601ff5303df03", + "reference": "f161e5d3a9e5ae573ca01cfb3b5601ff5303df03", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^8.2 || ^8.3 || ^8.4 || ^8.5", + "phpunit/phpunit": "^11.5 || ^12.0 || ^13.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" + } + ], + "description": "Assertion methods used by Codeception core and Asserts module", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-asserts/issues", + "source": "https://github.com/Codeception/lib-asserts/tree/3.2.0" + }, + "time": "2026-02-06T15:19:32+00:00" + }, + { + "name": "codeception/lib-innerbrowser", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-innerbrowser.git", + "reference": "8af7f8402f976b32f67a83dfd4e31f8f5b1f7db3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/8af7f8402f976b32f67a83dfd4e31f8f5b1f7db3", + "reference": "8af7f8402f976b32f67a83dfd4e31f8f5b1f7db3", + "shasum": "" + }, + "require": { + "codeception/codeception": "^5.0.8", + "codeception/lib-web": "^1.0.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "symfony/browser-kit": "^4.4.24 || ^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/dom-crawler": "^4.4.30 || ^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "require-dev": { + "codeception/util-universalframework": "^1.0 || ^2.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "https://codegyre.com" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Parent library for all Codeception framework modules and PhpBrowser", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-innerbrowser/issues", + "source": "https://github.com/Codeception/lib-innerbrowser/tree/4.1.0" + }, + "time": "2026-02-07T10:09:13+00:00" + }, + { + "name": "codeception/lib-web", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-web.git", + "reference": "a030a3a22fc8e856b5957086794ed5403c7992d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-web/zipball/a030a3a22fc8e856b5957086794ed5403c7992d9", + "reference": "a030a3a22fc8e856b5957086794ed5403c7992d9", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "guzzlehttp/psr7": "^2.0", + "php": "^8.2", + "phpunit/phpunit": "^11.5 | ^12 | ^13", + "symfony/css-selector": ">=4.4.24 <9.0" + }, + "conflict": { + "codeception/codeception": "<5.0.0-alpha3" + }, + "require-dev": { + "php-webdriver/webdriver": "^1.12" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gintautas Miselis" + } + ], + "description": "Library containing files used by module-webdriver and lib-innerbrowser or module-phpbrowser", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-web/issues", + "source": "https://github.com/Codeception/lib-web/tree/2.1.0" + }, + "time": "2026-02-06T15:22:13+00:00" + }, + { + "name": "codeception/module-asserts", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-asserts.git", + "reference": "3b4ec5dc771a135e13c79f7e9a6eacd74779e4ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/3b4ec5dc771a135e13c79f7e9a6eacd74779e4ad", + "reference": "3b4ec5dc771a135e13c79f7e9a6eacd74779e4ad", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "codeception/lib-asserts": "^3.1", + "php": "^8.2" + }, + "conflict": { + "codeception/codeception": "<5.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" + } + ], + "description": "Codeception module containing various assertions", + "homepage": "https://codeception.com/", + "keywords": [ + "assertions", + "asserts", + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/module-asserts/issues", + "source": "https://github.com/Codeception/module-asserts/tree/3.3.0" + }, + "time": "2025-12-23T21:16:13+00:00" + }, + { + "name": "codeception/module-cli", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-cli.git", + "reference": "a3a101fae4049fa2f810107f7bd5db3b3266ce63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-cli/zipball/a3a101fae4049fa2f810107f7bd5db3b3266ce63", + "reference": "a3a101fae4049fa2f810107f7bd5db3b3266ce63", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "codeception/module-asserts": "*", + "php": "^7.4 || ^8.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + } + ], + "description": "Codeception module for testing basic shell commands and shell output", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/module-cli/issues", + "source": "https://github.com/Codeception/module-cli/tree/2.0.1" + }, + "time": "2023-01-13T18:41:03+00:00" + }, + { + "name": "codeception/module-phpbrowser", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-phpbrowser.git", + "reference": "495a2cf19c4d0f1004bc24e10ed9d3cf33ccdc51" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-phpbrowser/zipball/495a2cf19c4d0f1004bc24e10ed9d3cf33ccdc51", + "reference": "495a2cf19c4d0f1004bc24e10ed9d3cf33ccdc51", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "codeception/lib-innerbrowser": "*@dev", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.4", + "php": "^8.2", + "symfony/browser-kit": "^5.4 | ^6.0 | ^7.0 | ^8.0" + }, + "conflict": { + "codeception/codeception": "<5.0", + "codeception/lib-innerbrowser": "<3.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.199", + "codeception/module-rest": "^2.0 | *@dev", + "ext-curl": "*", + "phpstan/phpstan": "^1.10", + "squizlabs/php_codesniffer": "^3.10" + }, + "suggest": { + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Codeception module for testing web application over HTTP", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception", + "functional-testing", + "http" + ], + "support": { + "issues": "https://github.com/Codeception/module-phpbrowser/issues", + "source": "https://github.com/Codeception/module-phpbrowser/tree/4.0.0" + }, + "time": "2026-01-23T13:24:41+00:00" + }, + { + "name": "codeception/stub", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Stub.git", + "reference": "6305b97eaf6ea9bdaed29a5bd4d6f2948f577d8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/6305b97eaf6ea9bdaed29a5bd4d6f2948f577d8f", + "reference": "6305b97eaf6ea9bdaed29a5bd4d6f2948f577d8f", + "shasum": "" + }, + "require": { + "php": "^8.1", + "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | ^11 | ^12 | ^13" + }, + "conflict": { + "codeception/codeception": "<5.0.6" + }, + "require-dev": { + "consolidation/robo": "^4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "support": { + "issues": "https://github.com/Codeception/Stub/issues", + "source": "https://github.com/Codeception/Stub/tree/4.3.0" + }, + "time": "2026-02-06T15:19:04+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "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": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "danog/advanced-json-rpc", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/danog/php-advanced-json-rpc.git", + "reference": "ae703ea7b4811797a10590b6078de05b3b33dd91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/danog/php-advanced-json-rpc/zipball/ae703ea7b4811797a10590b6078de05b3b33dd91", + "reference": "ae703ea7b4811797a10590b6078de05b3b33dd91", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^5", + "php": ">=8.1", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0 || ^6" + }, + "replace": { + "felixfbecker/php-advanced-json-rpc": "^3" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/danog/php-advanced-json-rpc/issues", + "source": "https://github.com/danog/php-advanced-json-rpc/tree/v3.2.3" + }, + "time": "2026-01-12T21:07:10+00:00" + }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=14" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^14", + "phpstan/phpstan": "1.4.10 || 2.1.30", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.6" + }, + "time": "2026-02-07T07:09:04+00:00" + }, + { + "name": "ergebnis/agent-detector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/agent-detector.git", + "reference": "5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64", + "reference": "5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64", + "shasum": "" + }, + "require": { + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.50.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.60.2", + "ergebnis/phpstan-rules": "^2.13.1", + "ergebnis/phpunit-slow-test-detector": "^2.24.0", + "ergebnis/rector-rules": "^1.16.0", + "fakerphp/faker": "^1.24.1", + "infection/infection": "^0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.46", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "phpunit/phpunit": "^9.6.34", + "rector/rector": "^2.4.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\AgentDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a detector for detecting the presence of an agent.", + "homepage": "https://github.com/ergebnis/agent-detector", + "support": { + "issues": "https://github.com/ergebnis/agent-detector/issues", + "security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/agent-detector" + }, + "time": "2026-04-10T13:45:13+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.3", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.3" + }, + "time": "2024-04-30T00:40:11+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.95.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "a9727678fbd12997f1d9de8f4a37824ed9df1065" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a9727678fbd12997f1d9de8f4a37824ed9df1065", + "reference": "a9727678fbd12997f1d9de8f4a37824ed9df1065", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.3", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.5", + "ergebnis/agent-detector": "^1.1.1", + "ext-filter": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.3", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.8.0", + "infection/infection": "^0.32.6", + "justinrainbow/json-schema": "^6.8.0", + "keradus/cli-executor": "^2.3", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.8", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.8" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/**/Internal/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.1" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2026-04-12T17:00:09+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.10.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "shasum": "" + }, + "require": { + "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/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": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "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": "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": "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/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + }, + "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": "guzzlehttp/promises", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "481557b130ef3790cf82b713667b43030dc9c957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "shasum": "" + }, + "require": { + "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": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "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": "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": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" + }, + "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": "guzzlehttp/psr7", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", + "shasum": "" + }, + "require": { + "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", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "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" + }, + { + "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": "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/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.9.0" + }, + "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": "2026-03-10T16:41:02+00:00" + }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Kelunik\\Certificate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Access certificate details and transform between different formats.", + "keywords": [ + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" + ], + "support": { + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" + }, + "time": "2023-02-03T21:26:53+00:00" + }, + { + "name": "league/uri", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.8.1", + "php": "^8.1", + "psr/http-factory": "^1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", + "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", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-components": "to provide additional tools to manipulate URI objects components", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", + "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": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "URN", + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc2141", + "rfc3986", + "rfc3987", + "rfc6570", + "rfc8141", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "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.8.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-03-15T20:22:25+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.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", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", + "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": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "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.8.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-03-08T20:05:35+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": "netresearch/jsonmapper", + "version": "v5.0.1", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "980674efdda65913492d29a8fd51c82270dd37bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/980674efdda65913492d29a8fd51c82270dd37bb", + "reference": "980674efdda65913492d29a8fd51c82270dd37bb", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v5.0.1" + }, + "time": "2026-02-22T16:28:03+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "6.0.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", + "webmozart/assert": "^1.9.1 || ^2" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3" + }, + "time": "2026-03-18T20:49:53+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/2.0.0" + }, + "time": "2026-01-06T21:53:42+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" + }, + "time": "2026-01-25T14:56:51+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.49", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d0082955396e7f5ba19cf298224b85e1099f0ed8", + "reference": "d0082955396e7f5ba19cf298224b85e1099f0ed8", + "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-04-16T21:10:58+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "13.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2ea1bcdad040326c02edd6519cc9d1c5a9f6c87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2ea1bcdad040326c02edd6519cc9d1c5a9f6c87e", + "reference": "2ea1bcdad040326c02edd6519cc9d1c5a9f6c87e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.7.0", + "php": ">=8.4", + "phpunit/php-text-template": "^6.0", + "sebastian/complexity": "^6.0", + "sebastian/environment": "^9.0", + "sebastian/lines-of-code": "^5.0", + "sebastian/version": "^7.0", + "theseer/tokenizer": "^2.0.1" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "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": "13.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/13.0.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/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2026-04-01T14:12:38+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.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": "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/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:33:26+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^13.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "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": "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/7.0.0" + }, + "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-invoker", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:34:47+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/a47af19f93f76aa3368303d752aa5272ca3299f4", + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "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/6.0.0" + }, + "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-text-template", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:36:37+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "9.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.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/9.0.0" + }, + "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-timer", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:37:53+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "13.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "9e426f7282c313c9138eeb9f25461e1a6be1e647" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9e426f7282c313c9138eeb9f25461e1a6be1e647", + "reference": "9e426f7282c313c9138eeb9f25461e1a6be1e647", + "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.4.1", + "phpunit/php-code-coverage": "^13.0.1", + "phpunit/php-file-iterator": "^7.0.0", + "phpunit/php-invoker": "^7.0.0", + "phpunit/php-text-template": "^6.0.0", + "phpunit/php-timer": "^9.0.0", + "sebastian/cli-parser": "^5.0.0", + "sebastian/comparator": "^8.0.0", + "sebastian/diff": "^8.0.0", + "sebastian/environment": "^9.1.0", + "sebastian/exporter": "^8.0.0", + "sebastian/global-state": "^9.0.0", + "sebastian/object-enumerator": "^8.0.0", + "sebastian/recursion-context": "^8.0.0", + "sebastian/type": "^7.0.0", + "sebastian/version": "^7.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "13.0-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/13.0.6" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsoring.html", + "type": "other" + } + ], + "time": "2026-03-31T06:44:39+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": "psy/psysh", + "version": "v0.12.22", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3be75d5b9244936dd4ac62ade2bfb004d13acf0f", + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^8.0 || ^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", + "composer/class-map-generator": "^1.6" + }, + "suggest": { + "composer/class-map-generator": "Improved tab completion performance with better class discovery.", + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "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.22" + }, + "time": "2026-03-22T23:03:24+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": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.7", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-12-23T15:25:20+00:00" + }, + { + "name": "react/dns", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.14.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-18T19:34:28+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-17T20:46:25+00:00" + }, + { + "name": "react/promise", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.12.28 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-08-19T18:57:03+00:00" + }, + { + "name": "react/socket", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.17.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-19T20:47:34+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "rector/rector", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "e645b6463c6a88ea5b44b17d3387d35a912c7946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/e645b6463c6a88ea5b44b17d3387d35a912c7946", + "reference": "e645b6463c6a88ea5b44b17d3387d35a912c7946", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.48" + }, + "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.4.2" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2026-04-16T13:07:34+00:00" + }, + { + "name": "revolt/event-loop", + "version": "v1.0.8", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/b6fc06dce8e9b523c9946138fa5e62181934f91c", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.8" + }, + "time": "2025-08-27T21:33:23+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "61130731cdf896e60028ed82193a1bc3c50d032a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/61130731cdf896e60028ed82193a1bc3c50d032a", + "reference": "61130731cdf896e60028ed82193a1bc3c50d032a", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "adaptcms/adaptcms": "<=1.3", + "admidio/admidio": "<5.0.8", + "adodb/adodb-php": "<=5.22.9", + "aheinze/cockpit": "<2.2", + "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", + "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", + "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", + "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", + "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", + "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-laravel": "==2021.10", + "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", + "airesvsg/acf-to-rest-api": "<=3.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<=1.5.2", + "alexusmai/laravel-file-manager": "<=3.3.1", + "algolia/algoliasearch-magento-2": "<=3.16.1|>=3.17.0.0-beta1,<=3.17.1", + "alt-design/alt-redirect": "<1.6.4", + "altcha-org/altcha": "<1.3.1", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "ameos/ameos_tarteaucitron": "<1.2.23", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<=1.7.2|>=2,<=2.1", + "amphp/http-client": ">=4,<4.4", + "amphp/http-server": ">=2.0.0.0-RC1-dev,<2.1.10|>=3.0.0.0-beta1,<3.4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", + "aoe/restler": "<1.7.1", + "apache-solr-for-typo3/solr": "<2.8.3", + "apereo/phpcas": "<1.6", + "api-platform/core": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "api-platform/graphql": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "artesaos/seotools": "<0.17.2", + "asymmetricrypt/asymmetricrypt": "<9.9.99", + "athlon1600/php-proxy": "<=5.1", + "athlon1600/php-proxy-app": "<=3", + "athlon1600/youtube-downloader": "<=4", + "aureuserp/aureuserp": "<1.3.0.0-beta1", + "austintoddj/canvas": "<=3.4.2", + "auth0/auth0-php": ">=3.3,<=8.18", + "auth0/login": "<7.20", + "auth0/symfony": "<=5.5", + "auth0/wordpress": "<=5.4", + "automad/automad": "<2.0.0.0-alpha5", + "automattic/jetpack": "<9.8", + "avideo/avideo": "<=26", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": "<=3.371.3", + "ayacoo/redirect-tab": "<2.1.2|>=3,<3.1.7|>=4,<4.0.5", + "azuracast/azuracast": "<=0.23.3", + "b13/seo_basics": "<0.8.2", + "backdrop/backdrop": "<=1.32", + "backpack/crud": "<3.4.9", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", + "bacula-web/bacula-web": "<9.7.1", + "badaso/core": "<=2.9.11", + "bagisto/bagisto": "<2.3.10", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.8", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<=5.2.2", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bbpress/bbpress": "<2.6.5", + "bcit-ci/codeigniter": "<3.1.3", + "bcosca/fatfree": "<3.7.2", + "bedita/bedita": "<4", + "bednee/cooluri": "<1.0.30", + "bigfork/silverstripe-form-capture": ">=3,<3.1.1", + "billz/raspap-webgui": "<3.3.6", + "binarytorch/larecipe": "<2.8.1", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "blueimp/jquery-file-upload": "==6.4.4", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "born05/craft-twofactorauthentication": "<3.3.4", + "bottelet/flarepoint": "<2.2.1", + "bref/bref": "<2.1.17", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bvbmedia/multishop": "<2.0.39", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cadmium-org/cadmium-cms": "<=0.4.9", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", + "cardgate/woocommerce": "<=3.1.15", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "causal/oidc": "<4", + "cecil/cecil": "<7.47.1", + "centreon/centreon": "<22.10.15", + "cesargb/laravel-magiclink": ">=2,<2.25.1", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "chriskacerguis/codeigniter-restserver": "<=2.7.1", + "chrome-php/chrome": "<1.14", + "ci4-cms-erp/ci4ms": "<=0.28.6", + "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", + "ckeditor/ckeditor": "<4.25", + "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", + "co-stack/fal_sftp": "<0.2.6", + "cockpit-hq/cockpit": "<2.13.5", + "code16/sharp": "<9.20", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<3.1.10", + "codeigniter4/framework": "<4.6.2", + "codeigniter4/shield": "<1.0.0.0-beta8", + "codiad/codiad": "<=2.8.4", + "codingms/additional-tca": ">=1.7,<1.15.17|>=1.16,<1.16.9", + "codingms/modules": "<4.3.11|>=5,<5.7.4|>=6,<6.4.2|>=7,<7.5.5", + "commerceteam/commerce": ">=0.9.6,<0.9.9", + "components/jquery": ">=1.0.3,<3.5", + "composer/composer": "<1.10.27|>=2,<2.2.26|>=2.3,<2.9.3", + "concrete5/concrete5": "<9.4.8", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", + "contao/contao": ">=3,<3.5.37|>=4,<4.4.56|>=4.5,<4.13.56|>=5,<5.3.38|>=5.4.0.0-RC1-dev,<5.6.1", + "contao/core": "<3.5.39", + "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", + "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "coreshop/core-shop": "<4.1.9", + "corveda/phpsandbox": "<1.3.5", + "cosenary/instagram": "<=2.3", + "couleurcitron/tarteaucitron-wp": "<0.3", + "cpsit/typo3-mailqueue": "<0.4.5|>=0.5,<0.5.2", + "craftcms/aws-s3": ">=2.0.2,<=2.2.4", + "craftcms/azure-blob": ">=2.0.0.0-beta1,<=2.1", + "craftcms/cms": "<=4.17.7|>=5,<=5.9.13", + "craftcms/commerce": ">=4,<4.11|>=5,<5.6", + "craftcms/composer": ">=4.0.0.0-RC1-dev,<=4.10|>=5.0.0.0-RC1-dev,<=5.5.1", + "craftcms/craft": ">=3.5,<=4.16.17|>=5.0.0.0-RC1-dev,<=5.8.21", + "craftcms/google-cloud": ">=2.0.0.0-beta1,<=2.2", + "craftcms/webhooks": ">=3,<3.2", + "croogo/croogo": "<=4.0.7", + "cuyz/valinor": "<0.12", + "czim/file-handling": "<1.5|>=2,<2.3", + "czproject/git-php": "<4.0.3", + "damienharper/auditor-bundle": "<5.2.6", + "dapphp/securimage": "<3.6.6", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "datahihi1/tiny-env": "<1.0.3|>=1.0.9,<1.0.11", + "datatables/datatables": "<1.10.10", + "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", + "desperado/xml-bundle": "<=0.1.7", + "dev-lancer/minecraft-motd-parser": "<=1.0.5", + "devcode-it/openstamanager": "<=2.10.1", + "devgroup/dotplant": "<2020.09.14-dev", + "digimix/wp-svg-upload": "<=1", + "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", + "directorytree/imapengine": "<1.22.3", + "dl/yag": "<3.0.1", + "dmk/webkitpdf": "<1.1.4", + "dnadesign/silverstripe-elemental": "<5.3.12", + "doctrine/annotations": "<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": "<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<0.7.2", + "doctrine/mongodb-odm": "<1.0.2", + "doctrine/mongodb-odm-bundle": "<3.0.1", + "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<=22.0.4", + "dompdf/dompdf": "<2.0.4", + "doublethreedigital/guest-entries": "<3.1.2", + "dreamfactory/df-core": "<1.0.4", + "drupal-pattern-lab/unified-twig-extensions": "<=0.1", + "drupal/access_code": "<2.0.5", + "drupal/acquia_dam": "<1.1.5", + "drupal/admin_audit_trail": "<1.0.5", + "drupal/ai": "<1.0.5", + "drupal/alogin": "<2.0.6", + "drupal/cache_utility": "<1.2.1", + "drupal/civictheme": "<1.12", + "drupal/commerce_alphabank_redirect": "<1.0.3", + "drupal/commerce_eurobank_redirect": "<2.1.1", + "drupal/config_split": "<1.10|>=2,<2.0.2", + "drupal/core": ">=6,<6.38|>=7,<7.103|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", + "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/currency": "<3.5", + "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/email_tfa": "<2.0.6", + "drupal/formatter_suite": "<2.1", + "drupal/gdpr": "<3.0.1|>=3.1,<3.1.2", + "drupal/google_tag": "<1.8|>=2,<2.0.8", + "drupal/ignition": "<1.0.4", + "drupal/json_field": "<1.5", + "drupal/lightgallery": "<1.6", + "drupal/link_field_display_mode_formatter": "<1.6", + "drupal/matomo": "<1.24", + "drupal/oauth2_client": "<4.1.3", + "drupal/oauth2_server": "<2.1", + "drupal/obfuscate": "<2.0.1", + "drupal/plausible_tracking": "<1.0.2", + "drupal/quick_node_block": "<2", + "drupal/rapidoc_elements_field_formatter": "<1.0.1", + "drupal/reverse_proxy_header": "<1.1.2", + "drupal/simple_multistep": "<2", + "drupal/simple_oauth": ">=6,<6.0.7", + "drupal/spamspan": "<3.2.1", + "drupal/tfa": "<1.10", + "drupal/umami_analytics": "<1.0.1", + "duncanmcclean/guest-entries": "<3.1.2", + "dweeves/magmi": "<=0.7.24", + "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.3.1", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "egroupware/egroupware": "<23.1.20260113|>=26.0.20251208,<26.0.20260113", + "elefant/cms": "<2.0.7", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "elijaa/phpmemcacheadmin": "<=1.3", + "elmsln/haxcms": "<11.0.14", + "encore/laravel-admin": "<=1.8.19", + "endroid/qr-code-bundle": "<3.4.2", + "enhavo/enhavo-app": "<=0.13.1", + "enshrined/svg-sanitize": "<0.22", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "evolutioncms/evolution": "<=3.2.3", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "<2.2.3|==3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1-dev", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1-dev", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1-dev|>=5.4,<5.4.11.1-dev|>=2017.12,<2017.12.0.1-dev", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.39|>=3.3,<3.3.39", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", + "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", + "ezsystems/ezplatform-http-cache": "<2.3.16", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.35", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", + "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.31", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<=4.2", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<2025.81", + "fastly/magento2": "<1.2.26", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filament/actions": ">=3.2,<3.2.123", + "filament/filament": ">=4,<4.3.1", + "filament/infolists": ">=3,<3.2.115", + "filament/tables": ">=3,<3.2.115|>=4,<4.8.5|>=5,<5.3.5", + "filegator/filegator": "<7.8", + "filp/whoops": "<2.1.13", + "fineuploader/php-traditional-server": "<=1.2.2", + "firebase/php-jwt": "<7", + "fisharebest/webtrees": "<=2.1.18", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=1.2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.8.10", + "flarum/flarum": "<0.1.0.0-beta8", + "flarum/framework": "<1.8.10", + "flarum/mentions": "<1.6.3", + "flarum/nicknames": "<1.8.3", + "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", + "flarum/tags": "<=0.1.0.0-beta13", + "floriangaerber/magnesium": "<0.3.1", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", + "fof/pretty-mail": "<=1.1.2", + "fof/upload": "<1.2.3", + "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<=11.5.1", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1,<1.3.5", + "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", + "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", + "froala/wysiwyg-editor": "<=4.3", + "frosh/adminer-platform": "<2.2.1", + "froxlor/froxlor": "<=2.3.4", + "frozennode/administrator": "<=5.0.12", + "fuel/core": "<1.8.1", + "funadmin/funadmin": "<=7.1.0.0-RC4", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "georgringer/news": "<1.3.3", + "geshi/geshi": "<=1.0.9.1", + "getformwork/formwork": "<=2.3.3", + "getgrav/grav": "<1.11.0.0-beta1", + "getkirby/cms": "<=5.2.1", + "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.15.4", + "gleez/cms": "<=1.3|==2", + "globalpayments/php-sdk": "<2", + "goalgorilla/open_social": "<12.3.11|>=12.4,<12.4.10|>=13.0.0.0-alpha1,<13.0.0.0-alpha11", + "gogentooss/samlbase": "<1.2.7", + "google/protobuf": "<4.33.6", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gp247/core": "<1.1.24", + "gree/jose": "<2.2.1", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<6.1.17|>=6.4.23,<=6.5", + "gugoan/economizzer": "<=0.9.0.0-beta1", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/oauth-subscriber": "<0.8.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", + "handcraftedinthealps/goodby-csv": "<1.4.3", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "<=2.31", + "hhxsv5/laravel-s": "<3.7.36", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", + "hybridauth/hybridauth": "<=3.12.2", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/admin-ui-assets": ">=4.6.0.0-alpha1,<4.6.21", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3|>=4.5,<4.5.6|>=4.6,<4.6.2", + "ibexa/fieldtype-richtext": ">=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/http-cache": ">=4.6,<4.6.14", + "ibexa/post-install": "<1.0.16|>=4.6,<4.6.14", + "ibexa/solr": ">=4.5,<4.5.4", + "ibexa/user": ">=4,<4.4.3|>=5,<5.0.4", + "icecoder/icecoder": "<=8.1", + "idno/known": "<1.6.4", + "ilicmiljan/secure-props": ">=1.2,<1.2.2", + "illuminate/auth": "<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "imdbphp/imdbphp": "<=5.1.1", + "impresscms/impresscms": "<=1.4.5", + "impresspages/impresspages": "<1.0.13", + "in2code/femanager": "<6.4.2|>=7,<7.5.3|>=8,<8.3.1", + "in2code/ipandlanguageredirect": "<5.1.2", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "in2code/powermail": "<7.5.1|>=8,<8.5.1|>=9,<10.9.1|>=11,<12.5.3|==13", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<4.2.2", + "inter-mediator/inter-mediator": "==5.5", + "invoiceninja/invoiceninja": "<5.13.4", + "ipl/web": "<0.10.1", + "islandora/crayfish": "<4.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "j0k3r/graby": "<=2.5", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "jambagecom/div2007": "<0.10.2", + "james-heinrich/getid3": "<1.9.21", + "james-heinrich/phpthumb": "<=1.7.23", + "jasig/phpcas": "<1.3.3", + "jbartels/wec-map": "<3.0.3", + "jcbrand/converse.js": "<3.3.3", + "joelbutcher/socialstream": "<5.6|>=6,<6.2", + "johnbillion/query-monitor": "<3.20.4", + "johnbillion/wp-crontrol": "<1.16.2|>=1.17,<1.19.2", + "joomla/application": "<1.0.13", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/database": ">=1,<2.2|>=3,<3.4", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<2.0.6|>=3,<3.0.5|==4", + "joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12", + "joomla/input": ">=2,<2.0.2", + "joomla/joomla-cms": "<3.9.12|>=4,<4.4.13|>=5,<5.2.6", + "joomla/joomla-platform": "<1.5.4", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "juzaweb/cms": "<=3.4.2", + "jweiland/events2": "<8.3.8|>=9,<9.0.6", + "jweiland/kk-downloader": "<1.2.2", + "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplejwt": "<=1.1", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "khodakhah/nodcms": "<=3", + "kimai/kimai": "<=2.50", + "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", + "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<=1.4.2", + "kohana/core": "<3.3.3", + "koillection/koillection": "<1.6.12", + "krayin/laravel-crm": "<=1.3", + "kreait/firebase-php": ">=3.2,<3.8.1", + "kumbiaphp/kumbiapp": "<=1.1.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.18.1|==2.19|==2.20|==2.21|==2.22|==2.23|>=2.24,<2.24.2|>=2.25,<2.25.2", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "lara-zeus/artemis": ">=1,<=1.0.6", + "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", + "laravel/laravel": ">=5.4,<5.4.22", + "laravel/pulse": "<1.3.1", + "laravel/reverb": "<1.7", + "laravel/socialite": ">=1,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=10.1", + "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<=2.8.1", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", + "leantime/leantime": "<3.3", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "libreform/libreform": ">=2,<=2.0.8", + "librenms/librenms": "<26.3", + "liftkit/database": "<2.13.2", + "lightsaml/lightsaml": "<1.3.5", + "limesurvey/limesurvey": "<6.15.4", + "livehelperchat/livehelperchat": "<=3.91", + "livewire-filemanager/filemanager": "<=1.0.4", + "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", + "livewire/volt": "<1.7", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "lomkit/laravel-rest-api": "<2.13", + "luracast/restler": "<3.1", + "luyadev/yii-helpers": "<1.2.1", + "macropay-solutions/laravel-crud-wizard-free": "<3.4.17", + "maestroerror/php-heic-to-jpg": "<1.0.5", + "magento/community-edition": "<2.4.6.0-patch13|>=2.4.7.0-beta1,<2.4.7.0-patch8|>=2.4.8.0-beta1,<2.4.8.0-patch3|>=2.4.9.0-alpha1,<2.4.9.0-alpha3|==2.4.9", + "magento/core": "<=1.9.4.5", + "magento/magento1ce": "<1.9.4.3-dev", + "magento/magento1ee": ">=1,<1.14.4.3-dev", + "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", + "magento/project-community-edition": "<=2.0.2", + "magneto/core": "<1.9.4.4-dev", + "mahocommerce/maho": "<25.9", + "maikuolan/phpmussel": ">=1,<1.6", + "mainwp/mainwp": "<=4.4.3.3", + "manogi/nova-tiptap": "<=3.2.6", + "mantisbt/mantisbt": "<2.28.1", + "marcwillmann/turn": "<0.3.3", + "marshmallow/nova-tiptap": "<5.7", + "matomo/matomo": "<1.11", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<5.2.10|>=6,<6.0.8|>=7.0.0.0-alpha,<7.0.1", + "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", + "mautic/grapes-js-builder-bundle": ">=4,<4.4.18|>=5,<5.2.9|>=6,<6.0.7", + "maximebf/debugbar": "<1.19", + "mdanter/ecc": "<2", + "mediawiki/abuse-filter": "<1.39.9|>=1.40,<1.41.3|>=1.42,<1.42.2", + "mediawiki/cargo": "<3.8.3", + "mediawiki/core": "<1.39.5|==1.40", + "mediawiki/data-transfer": ">=1.39,<1.39.11|>=1.41,<1.41.3|>=1.42,<1.42.2", + "mediawiki/matomo": "<2.4.3", + "mediawiki/semantic-media-wiki": "<4.0.2", + "mehrwert/phpmyadmin": "<3.2", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.3.4", + "melisplatform/melis-cms-slider": "<5.3.1", + "melisplatform/melis-core": "<5.3.11", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", + "microsoft/microsoft-graph-beta": "<2.0.1", + "microsoft/microsoft-graph-core": "<2.0.2", + "microweber/microweber": "<2.0.20", + "mikehaertl/php-shellcommand": "<1.6.1", + "mineadmin/mineadmin": "<=3.0.9", + "miniorange/miniorange-saml": "<1.4.3", + "miraheze/ts-portal": "<=33", + "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", + "modx/revolution": "<=3.1", + "mojo42/jirafeau": "<4.4", + "mongodb/mongodb": ">=1,<1.9.2", + "mongodb/mongodb-extension": "<1.21.2", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.5.9|>=5.0.0.0-beta,<5.0.5|>=5.1.0.0-beta,<5.1.2", + "moonshine/moonshine": "<=3.12.5", + "mos/cimage": "<0.7.19", + "movim/moxl": ">=0.8,<=0.10", + "movingbytes/social-network": "<=1.2.1", + "mpdf/mpdf": "<=7.1.7", + "munkireport/comment": "<4", + "munkireport/managedinstalls": "<2.6", + "munkireport/munki_facts": "<1.5", + "munkireport/reportdata": "<3.5", + "munkireport/softwareupdate": "<1.6", + "mustache/mustache": ">=2,<2.14.1", + "mwdelaney/wp-enable-svg": "<=0.2", + "namshi/jose": "<2.2", + "nasirkhan/laravel-starter": "<11.11", + "nategood/httpful": "<1", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.04", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": "<5.4.5", + "nesbot/carbon": "<2.72.6|>=3,<3.8.4", + "netcarver/textile": "<=4.1.2", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "neuron-core/neuron-ai": "<=2.8.11", + "nilsteampassnet/teampass": "<3.1.3.1-dev", + "nitsan/ns-backup": "<13.0.1", + "nonfiction/nterchange": "<4.1.1", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "novaksolutions/infusionsoft-php-sdk": "<1", + "novosga/novosga": "<=2.2.12", + "nukeviet/nukeviet": "<4.5.02", + "nyholm/psr7": "<1.6.1", + "nystudio107/craft-seomatic": "<3.4.12", + "nzedb/nzedb": "<0.8", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", + "october/october": "<3.7.5", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<=3.7.12|>=4,<=4.0.11", + "oliverklee/phpunit": "<3.5.15", + "omeka/omeka-s": "<4.0.3", + "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", + "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.8.1", + "opencart/opencart": ">=0", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<20.16.1", + "opensolutions/vimbadmin": "<=3.0.15", + "opensource-workshop/connect-cms": "<1.41.1|>=2,<2.41.1", + "orchid/platform": ">=8,<14.43", + "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", + "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", + "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", + "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", + "oxid-esales/oxideshop-ce": "<=7.0.5", + "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": "<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/ecc": "<2.0.1", + "paragonie/random_compat": "<2", + "paragonie/sodium_compat": "<1.24|>=2,<2.5", + "passbolt/passbolt_api": "<4.6.2", + "paypal/adaptivepayments-sdk-php": "<=3.9.2", + "paypal/invoice-sdk-php": "<=3.9", + "paypal/merchant-sdk-php": "<3.12", + "paypal/permissions-sdk-php": "<=3.9.1", + "pear/archive_tar": "<1.4.14", + "pear/auth": "<1.2.4", + "pear/crypt_gpg": "<1.6.7", + "pear/http_request2": "<2.7", + "pear/pear": "<=1.10.1", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "ph7software/ph7builder": "<=17.9.1", + "phanan/koel": "<5.1.4", + "phenx/php-svg-lib": "<0.5.2", + "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": "<3.3.11", + "phpems/phpems": ">=6,<=6.1.3", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.2.2", + "phpmyfaq/phpmyfaq": "<=4.1", + "phpoffice/common": "<0.2.9", + "phpoffice/math": "<=0.2", + "phpoffice/phpexcel": "<=1.8.2", + "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", + "phppgadmin/phppgadmin": "<=7.13", + "phpseclib/phpseclib": "<=2.0.51|>=3,<=3.0.49", + "phpservermon/phpservermon": "<3.6", + "phpsysinfo/phpsysinfo": "<3.4.3", + "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "phraseanet/phraseanet": "==4.0.3", + "pi/pi": "<=2.5", + "pimcore/admin-ui-classic-bundle": "<=1.7.15|>=2.0.0.0-RC1-dev,<=2.2.2", + "pimcore/customer-management-framework-bundle": "<4.2.1", + "pimcore/data-hub": "<1.2.4", + "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", + "pimcore/demo": "<10.3", + "pimcore/ecommerce-framework-bundle": "<1.0.10", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<=11.5.14.1|>=12,<12.3.3", + "pimcore/web2print-tools-bundle": "<=5.2.1|>=6.0.0.0-RC1-dev,<=6.1", + "piwik/piwik": "<1.11", + "pixelfed/pixelfed": "<0.12.5", + "plotly/plotly.js": "<2.25.2", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<5.32.1", + "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockreassurance": "<=5.1.3", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": "<8.2.5|>=9.0.0.0-alpha1,<9.1", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", + "prestashop/ps_contactinfo": "<=3.3.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4|>=1.5,<1.7.4|>=1.7.7,<2.0.3", + "processwire/processwire": "<=3.0.246", + "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", + "propel/propel1": ">=1,<=1.7.1", + "psy/psysh": "<=0.11.22|>=0.12,<=0.12.18", + "pterodactyl/panel": "<1.12.1", + "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", + "ptrofimov/beanstalk_console": "<1.7.14", + "pubnub/pubnub": "<6.1", + "punktde/pt_extbase": "<1.5.1", + "pusher/pusher-php-server": "<2.2.1", + "putyourlightson/craft-sprig": ">=2,<2.15.2|>=3,<3.7.2", + "pwweb/laravel-core": "<=0.3.6.0-beta", + "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", + "pyrocms/pyrocms": "<=3.9.1", + "qcubed/qcubed": "<=3.1.1", + "quickapps/cms": "<=2.0.0.0-beta2", + "rainlab/blog-plugin": "<1.4.1", + "rainlab/debugbar-plugin": "<3.1", + "rainlab/user-plugin": "<=1.4.5", + "ralffreit/mfa-email": "<1.0.7|==2", + "rankmath/seo-by-rank-math": "<=1.0.95", + "rap2hpoutre/laravel-log-viewer": "<0.13", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", + "redaxo/source": "<=5.20.1", + "remdex/livehelperchat": "<4.29", + "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", + "reportico-web/reportico": "<=8.1", + "rhukster/dom-sanitizer": "<1.0.7", + "rmccue/requests": ">=1.6,<1.8", + "roadiz/documents": "<2.3.42|>=2.4,<2.5.44|>=2.6,<2.6.28|>=2.7,<2.7.9", + "robrichards/xmlseclibs": "<3.1.5", + "roots/soil": "<4.1", + "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11", + "rudloff/alltube": "<3.0.3", + "rudloff/rtmpdump-bin": "<=2.3.1", + "s-cart/core": "<=9.0.5", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", + "saloonphp/saloon": "<4", + "samwilson/unlinked-wikibase": "<1.42", + "scheb/two-factor-bundle": "<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "setasign/fpdi": "<2.6.4", + "sfroemken/url_redirect": "<=1.2.1", + "sheng/yiicms": "<1.2.1", + "shopware/core": "<6.6.10.15-dev|>=6.7,<6.7.8.1-dev", + "shopware/platform": "<6.6.10.15-dev|>=6.7,<6.7.8.1-dev", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.6.1-dev", + "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", + "shopxo/shopxo": "<=6.4", + "showdoc/showdoc": "<2.10.4", + "shuchkin/simplexlsx": ">=1.0.12,<1.1.13", + "silverstripe-australia/advancedreports": ">=1,<=2", + "silverstripe/admin": "<1.13.19|>=2,<2.1.8", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", + "silverstripe/comments": ">=1.3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<5.3.23", + "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/recipe-cms": ">=4.5,<4.5.3", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/reports": "<5.2.3", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3|>=5,<5.4.2", + "silverstripe/versioned-admin": ">=1,<1.11.1", + "simogeo/filemanager": "<=2.5", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<=4.16.15|>=5.0.0.0-alpha1,<=5.0.0.0-alpha19", + "simplesamlphp/saml2-legacy": "<=4.16.15", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", + "simplesamlphp/xml-common": "<1.20", + "simplesamlphp/xml-security": "<1.13.9|>=2,<2.3.1", + "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "sjbr/sr-feuser-register": "<2.6.2|>=5.1,<12.5", + "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", + "sjbr/static-info-tables": "<2.3.1", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", + "slim/slim": "<2.6", + "slub/slub-events": "<3.0.3", + "smarty/smarty": "<4.5.3|>=5,<5.1.1", + "snipe/snipe-it": "<8.3.7", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "solspace/craft-freeform": "<4.1.29|>=5,<=5.14.6", + "soosyze/soosyze": "<=2", + "spatie/browsershot": "<5.0.5", + "spatie/image-optimizer": "<1.7.3", + "spencer14420/sp-php-email-handler": "<1", + "spipu/html2pdf": "<5.2.8", + "spiral/roadrunner": "<2025.1", + "spoon/library": "<1.4.1", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<24.05.1", + "starcitizentools/citizen-skin": ">=1.9.4,<3.9", + "starcitizentools/short-description": ">=4,<4.0.1", + "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", + "starcitizenwiki/embedvideo": "<=4", + "statamic/cms": "<5.73.16|>=6,<6.7.2", + "stormpath/sdk": "<9.9.99", + "studio-42/elfinder": "<=2.1.64", + "studiomitte/friendlycaptcha": "<0.1.4", + "subhh/libconnect": "<7.0.8|>=8,<8.1", + "sukohi/surpass": "<1", + "sulu/form-bundle": ">=2,<2.5.3", + "sulu/sulu": "<2.6.22|>=3,<3.0.5", + "sumocoders/framework-user-bundle": "<1.4", + "superbig/craft-audit": "<3.0.2", + "svewap/a21glossary": "<=0.4.10", + "swag/paypal": "<5.4.4", + "swiftmailer/swiftmailer": "<6.2.5", + "swiftyedit/swiftyedit": "<1.2", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", + "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.9.12|>=1.10,<1.10.16|>=1.11,<1.11.17|>=1.12,<=1.12.22|>=1.13,<=1.13.14|>=1.14,<=1.14.17|>=2,<=2.0.15|>=2.1,<=2.1.11|>=2.2,<=2.2.2", + "symbiote/silverstripe-multivaluefield": ">=3,<3.1", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", + "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/http-foundation": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/process": "<5.4.51|>=6,<6.4.33|>=7,<7.1.7|>=7.3,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.4.10|>=7,<7.0.10|>=7.1,<7.1.3", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": "<5.4.51|>=6,<6.4.33|>=7,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", + "symfony/translation": ">=2,<2.0.17", + "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", + "symfony/ux-autocomplete": "<2.11.2", + "symfony/ux-live-component": "<2.25.1", + "symfony/ux-twig-component": "<2.25.1", + "symfony/validator": "<5.4.43|>=6,<6.4.11|>=7,<7.1.4", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/webhook": ">=6.3,<6.3.8", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7|>=2.2.0.0-beta1,<2.2.0.0-beta2", + "symphonycms/symphony-2": "<2.6.4", + "t3/dce": "<0.11.5|>=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "t3s/content-consent": "<1.0.3|>=2,<2.0.2", + "tastyigniter/tastyigniter": "<4", + "tcg/voyager": "<=1.8", + "tecnickcom/tc-lib-pdf-font": "<2.6.4", + "tecnickcom/tcpdf": "<6.8", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<6.0.8", + "thorsten/phpmyfaq": "<4.1.1", + "tikiwiki/tiki-manager": "<=17.1", + "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", + "tinymce/tinymce": "<7.2", + "tinymighty/wiki-seo": "<1.2.2", + "titon/framework": "<9.9.99", + "tltneon/lgsl": "<7", + "tobiasbg/tablepress": "<=2.0.0.0-RC1", + "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", + "topthink/think": "<=6.1.1", + "topthink/thinkphp": "<=3.2.3|>=6.1.3,<=8.0.4", + "torrentpier/torrentpier": "<=2.8.8", + "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", + "tribalsystems/zenario": "<=9.7.61188", + "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", + "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", + "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", + "typicms/core": "<16.1.7", + "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", + "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-felogin": ">=4.2,<4.2.3", + "typo3/cms-fluid": "<4.3.4|>=4.4,<4.4.1", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-frontend": "<4.3.9|>=4.4,<4.4.5", + "typo3/cms-indexed-search": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", + "typo3/cms-lowlevel": ">=11,<=11.5.41", + "typo3/cms-recordlist": ">=11,<11.5.48", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-redirects": ">=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", + "typo3/cms-scheduler": ">=11,<=11.5.41", + "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-webhooks": ">=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-workspaces": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<=1.5.2|>=2,<=2.1.3", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "uasoft-indonesia/badaso": "<=2.9.7", + "unisharp/laravel-filemanager": "<2.9.1", + "universal-omega/dynamic-page-list3": "<3.6.4", + "unopim/unopim": "<=0.3", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", + "uvdesk/core-framework": "<=1.1.1", + "vanilla/safecurl": "<0.9.2", + "verbb/comments": "<1.5.5", + "verbb/formie": "<=2.1.43", + "verbb/image-resizer": "<2.0.9", + "verbb/knock-knock": "<1.2.8", + "verot/class.upload.php": "<=2.1.6", + "vertexvaar/falsftp": "<0.2.6", + "villagedefrance/opencart-overclocked": "<=1.11.1", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<5.4.2", + "vufind/vufind": ">=2,<9.1.1", + "waldhacker/hcaptcha": "<2.1.2", + "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.6.11", + "wanglelecc/laracms": "<=1.0.3", + "wapplersystems/a21glossary": "<=0.4.10", + "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9|>=5.2,<5.2.4", + "web-auth/webauthn-lib": ">=4.5,<4.9|>=5.2,<5.2.4", + "web-auth/webauthn-symfony-bundle": ">=5.2,<5.2.4", + "web-feet/coastercms": "==5.5", + "web-tp3/wec_map": "<3.0.3", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webklex/laravel-imap": "<5.3", + "webklex/php-imap": "<5.3", + "webpa/webpa": "<3.1.2", + "webreinvent/vaahcms": "<=2.3.1", + "wikibase/wikibase": "<=1.39.3", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "winter/wn-backend-module": "<1.2.12", + "winter/wn-cms-module": "<=1.2.9", + "winter/wn-dusk-plugin": "<2.1", + "winter/wn-system-module": "<1.2.4", + "wintercms/winter": "<=1.2.3", + "wireui/wireui": "<1.19.3|>=2,<2.1.3", + "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", + "wp-cli/wp-cli": ">=0.12,<2.5", + "wp-graphql/wp-graphql": "<=1.14.5", + "wp-premium/gravityforms": "<2.4.21", + "wpanel/wpanel4-cms": "<=4.3.1", + "wpcloud/wp-stateless": "<3.2", + "wpglobus/wpglobus": "<=1.9.6", + "wpmetabox/meta-box": "<5.11.2", + "wwbn/avideo": "<=26", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yab/quarx": "<2.4.5", + "yansongda/pay": "<=3.7.19", + "yeswiki/yeswiki": "<4.6", + "yetiforce/yetiforce-crm": "<6.5", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": "<1.1.31", + "yiisoft/yii2": "<2.0.52", + "yiisoft/yii2-authclient": "<2.2.15", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<=2.0.45", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<=2.2.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.20", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yoast/duplicate-post": "<=4.5", + "yourls/yourls": "<=1.10.2", + "yuan1994/tpadmin": "<=1.3.12", + "yungifez/skuul": "<=2.6.5", + "z-push/z-push-dev": "<2.7.6", + "zencart/zencart": "<=1.5.7.0-beta", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": "<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": "<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": "<2.0.2", + "zendframework/zendrest": "<2.0.2", + "zendframework/zendservice-amazon": "<2.0.3", + "zendframework/zendservice-api": "<1", + "zendframework/zendservice-audioscrobbler": "<2.0.2", + "zendframework/zendservice-nirvanix": "<2.0.2", + "zendframework/zendservice-slideshare": "<2.0.2", + "zendframework/zendservice-technorati": "<2.0.2", + "zendframework/zendservice-windowsazure": "<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zenstruck/collection": "<0.2.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<=6.1.53", + "zumba/json-serializer": "<3.2.3" + }, + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } + ], + "time": "2026-04-02T00:32:12+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/48a4654fa5e48c1c81214e9930048a572d4b23ca", + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.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": "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/5.0.0" + }, + "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/cli-parser", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:39:44+00:00" + }, + { + "name": "sebastian/comparator", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "29b232ddc29c2b114c0358c69b3084e7c3da0d58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/29b232ddc29c2b114c0358c69b3084e7c3da0d58", + "reference": "29b232ddc29c2b114c0358c69b3084e7c3da0d58", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/diff": "^8.0", + "sebastian/exporter": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "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/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:40:39+00:00" + }, + { + "name": "sebastian/complexity", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "c5651c795c98093480df79350cb050813fc7a2f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c5651c795c98093480df79350cb050813fc7a2f3", + "reference": "c5651c795c98093480df79350cb050813fc7a2f3", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "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/6.0.0" + }, + "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/complexity", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:41:32+00:00" + }, + { + "name": "sebastian/diff", + "version": "8.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "9c957d730257f49c873f3761674559bd90098a7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/9c957d730257f49c873f3761674559bd90098a7d", + "reference": "9c957d730257f49c873f3761674559bd90098a7d", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.1-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/8.1.0" + }, + "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/diff", + "type": "tidelift" + } + ], + "time": "2026-04-05T12:02:33+00:00" + }, + { + "name": "sebastian/environment", + "version": "9.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "c4a2dc54b1a24e13ef1839cbb5947b967cbae853" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/c4a2dc54b1a24e13ef1839cbb5947b967cbae853", + "reference": "c4a2dc54b1a24e13ef1839cbb5947b967cbae853", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.1-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/9.1.0" + }, + "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": "2026-03-22T06:31:50+00:00" + }, + { + "name": "sebastian/exporter", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea", + "reference": "dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/8.0.0" + }, + "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": "2026-02-06T04:44:28+00:00" + }, + { + "name": "sebastian/global-state", + "version": "9.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e52e3dc22441e6218c710afe72c3042f8fc41ea7", + "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/9.0.0" + }, + "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": "2026-02-06T04:45:13+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "4f21bb7768e1c997722ccc7efb1d6b5c11bfd471" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/4f21bb7768e1c997722ccc7efb1d6b5c11bfd471", + "reference": "4f21bb7768e1c997722ccc7efb1d6b5c11bfd471", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.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": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/5.0.0" + }, + "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/lines-of-code", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:45:54+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/8.0.0" + }, + "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/object-enumerator", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:46:36+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/6.0.0" + }, + "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/object-reflector", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:47:13+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/74c5af21f6a5833e91767ca068c4d3dfec15317e", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/8.0.0" + }, + "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": "2026-02-06T04:51:28+00:00" + }, + { + "name": "sebastian/type", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "42412224607bd3931241bbd17f38e0f972f5a916" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/42412224607bd3931241bbd17f38e0f972f5a916", + "reference": "42412224607bd3931241bbd17f38e0f972f5a916", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.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": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:52:09+00:00" + }, + { + "name": "sebastian/version", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ad37a5552c8e2b88572249fdc19b6da7792e021b", + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "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": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/7.0.0" + }, + "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/version", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:52:52+00:00" + }, + { + "name": "shipmonk/composer-dependency-analyser", + "version": "1.8.4", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", + "reference": "975e5873b519d5180b1017a5dfb43d80781abd45" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/975e5873b519d5180b1017a5dfb43d80781abd45", + "reference": "975e5873b519d5180b1017a5dfb43d80781abd45", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.7.0", + "ergebnis/composer-normalize": "^2.19.0", + "ext-dom": "*", + "ext-libxml": "*", + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.26", + "phpstan/phpstan-phpunit": "^1.4.2", + "phpstan/phpstan-strict-rules": "^1.6.2", + "phpunit/phpunit": "^8.5.42 || ^9.6.23", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" + }, + "bin": [ + "bin/composer-dependency-analyser" + ], + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\ComposerDependencyAnalyser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Fast detection of composer dependency issues (dead dependencies, shadow dependencies, misplaced dependencies)", + "keywords": [ + "analyser", + "composer", + "composer dependency", + "dead code", + "dead dependency", + "detector", + "dev", + "misplaced dependency", + "shadow dependency", + "static analysis", + "unused code", + "unused dependency" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", + "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.4" + }, + "time": "2025-11-25T14:38:16+00:00" + }, + { + "name": "spatie/array-to-xml", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "88b2f3852a922dd73177a68938f8eb2ec70c7224" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/88b2f3852a922dd73177a68938f8eb2ec70c7224", + "reference": "88b2f3852a922dd73177a68938f8eb2ec70c7224", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/3.4.4" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-12-15T09:00:41+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "f5a28fca785416cf489dd579011e74c831100cc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f5a28fca785416cf489dd579011e74c831100cc3", + "reference": "f5a28fca785416cf489dd579011e74c831100cc3", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/dom-crawler": "^7.4|^8.0" + }, + "require-dev": { + "symfony/css-selector": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed", + "reference": "8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "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/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "284ace90732b445b027728b5e0eec6418a17a364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/284ace90732b445b027728b5e0eec6418a17a364", + "reference": "284ace90732b445b027728b5e0eec6418a17a364", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "symfony/css-selector": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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 DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f662acc6ab22a3d6d716dcb44c381c6002940df6", + "reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/security-http": "<7.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": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^7.4|^8.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/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "66b769ae743ce2d13e435528fbef4af03d623e5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/66b769ae743ce2d13e435528fbef4af03d623e5a", + "reference": "66b769ae743ce2d13e435528fbef4af03d623e5a", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/finder", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "8da41214757b87d97f181e3d14a4179286151007" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/8da41214757b87d97f181e3d14a4179286151007", + "reference": "8da41214757b87d97f181e3d14a4179286151007", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "symfony/filesystem": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "b48bce0a70b914f6953dafbd10474df232ed4de8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b48bce0a70b914f6953dafbd10474df232ed4de8", + "reference": "b48bce0a70b914f6953dafbd10474df232ed4de8", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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 an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "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\\Php81\\": "" + }, + "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.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.34.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-php84", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06", + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06", + "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.34.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": "2026-04-10T18:47:49+00:00" + }, + { + "name": "symfony/process", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc", + "reference": "cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "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/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/85954ed72d5440ea4dc9a10b7e49e01df766ffa3", + "reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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 way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "cfb7badd53bf4177f6e9416cfbbccc13c0e773a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cfb7badd53bf4177f6e9416cfbbccc13c0e773a1", + "reference": "cfb7badd53bf4177f6e9416cfbbccc13c0e773a1", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/console": "<7.4", + "symfony/error-handler": "<7.4" + }, + "require-dev": { + "symfony/console": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.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/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-31T07:15:36+00:00" + }, + { + "name": "symfony/yaml", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "54174ab48c0c0f9e21512b304be17f8150ccf8f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/54174ab48c0c0f9e21512b304be17f8150ccf8f1", + "reference": "54174ab48c0c0f9e21512b304be17f8150ccf8f1", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<7.4" + }, + "require-dev": { + "symfony/console": "^7.4|^8.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "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": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v8.0.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-30T15:14:47+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^8.1" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-12-08T11:19:18+00:00" + }, + { + "name": "vimeo/psalm", + "version": "6.16.1", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "f1f5de594dc76faf8784e02d3dc4716c91c6f6ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/f1f5de594dc76faf8784e02d3dc4716c91c6f6ac", + "reference": "f1f5de594dc76faf8784e02d3dc4716c91c6f6ac", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/parallel": "^2.3", + "composer-runtime-api": "^2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "danog/advanced-json-rpc": "^3.1", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/language-server-protocol": "^1.5.3", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", + "netresearch/jsonmapper": "^5.0", + "nikic/php-parser": "^5.0.0", + "php": "~8.1.31 || ~8.2.27 || ~8.3.16 || ~8.4.3 || ~8.5.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "spatie/array-to-xml": "^2.17.0 || ^3.0", + "symfony/console": "^6.0 || ^7.0 || ^8.0", + "symfony/filesystem": "~6.3.12 || ~6.4.3 || ^7.0.3 || ^8.0", + "symfony/polyfill-php84": "^1.31.0" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "amphp/phpunit-util": "^3", + "bamarni/composer-bin-plugin": "^1.4", + "brianium/paratest": "^6.9", + "danog/class-finder": "^0.4.8", + "dg/bypass-finals": "^1.5", + "ext-curl": "*", + "mockery/mockery": "^1.5", + "nunomaduro/mock-final-classes": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpdoc-parser": "^1.6", + "phpunit/phpunit": "^9.6", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.19", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^6.0 || ^7.0 || ^8.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalm-review", + "psalter" + ], + "type": "project", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev", + "dev-3.x": "3.x-dev", + "dev-4.x": "4.x-dev", + "dev-5.x": "5.x-dev", + "dev-6.x": "6.x-dev", + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php", + "static analysis" + ], + "support": { + "docs": "https://psalm.dev/docs", + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm" + }, + "time": "2026-03-19T10:56:09+00:00" + }, + { + "name": "webmozart/assert", + "version": "2.1.6", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/ff31ad6efc62e66e518fbab1cde3453d389bcdc8", + "reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-feature/2-0": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@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/2.1.6" + }, + "time": "2026-02-27T10:28:38+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "roave/security-advisories": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.5", + "ext-filter": "*", + "ext-intl": "*", + "ext-mbstring": "*" + }, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +} diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 0000000000000..8b60a947d4145 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1 @@ +.merge-plan.php diff --git a/config/api/di/application.php b/config/api/di/application.php new file mode 100644 index 0000000000000..2f2520e4c007b --- /dev/null +++ b/config/api/di/application.php @@ -0,0 +1,69 @@ + [ + '__construct()' => [ + 'dispatcher' => DynamicReference::to([ + 'class' => MiddlewareDispatcher::class, + 'withMiddlewares()' => [ + [ + ErrorCatcher::class, + static fn() => new ContentNegotiatorDataResponseMiddleware( + formatters: [ + 'application/xml' => new XmlFormatter(), + 'application/json' => new JsonFormatter(), + ], + fallback: new JsonFormatter(), + ), + static fn(ExceptionResponderFactory $factory) => $factory->create(), + RequestBodyParser::class, + Router::class, + NotFoundMiddleware::class, + ], + ], + ]), + ], + ], + + ParametersResolverInterface::class => [ + 'class' => CompositeParametersResolver::class, + '__construct()' => [ + DynamicReference::to([ + 'class' => HydratorAttributeParametersResolver::class, + '__construct()' => [ + 'typeCaster' => DynamicReference::to( + static fn() => new CompositeTypeCaster( + new PhpNativeTypeCaster(), + new HydratorTypeCaster(), + ), + ), + ], + ]), + Reference::to(RequestInputParametersResolver::class), + ], + ], +]; diff --git a/config/api/di/psr17.php b/config/api/di/psr17.php new file mode 100644 index 0000000000000..9787bb293b3cd --- /dev/null +++ b/config/api/di/psr17.php @@ -0,0 +1,25 @@ + RequestFactory::class, + ServerRequestFactoryInterface::class => ServerRequestFactory::class, + ResponseFactoryInterface::class => ResponseFactory::class, + StreamFactoryInterface::class => StreamFactory::class, + UriFactoryInterface::class => UriFactory::class, + UploadedFileFactoryInterface::class => UploadedFileFactory::class, +]; diff --git a/config/api/params.php b/config/api/params.php new file mode 100644 index 0000000000000..2b3b658476d95 --- /dev/null +++ b/config/api/params.php @@ -0,0 +1,11 @@ + [ + 'requestInputParametersResolver' => [ + 'throwInputValidationException' => true, + ], + ], +]; diff --git a/config/api/routes.php b/config/api/routes.php new file mode 100644 index 0000000000000..d7762f35bb838 --- /dev/null +++ b/config/api/routes.php @@ -0,0 +1,10 @@ +action(\App\UseCase\Diary\Api\Category\List\Action::class), + Route::get('/diary/post/list')->action(\App\UseCase\Diary\Api\Post\List\Action::class), +]; diff --git a/config/common/aliases.php b/config/common/aliases.php new file mode 100644 index 0000000000000..272e8a8b8b441 --- /dev/null +++ b/config/common/aliases.php @@ -0,0 +1,15 @@ + dirname(__DIR__, 2), + '@src' => '@root/src', + '@assets' => '@root/public/assets', + '@assetsUrl' => '@baseUrl/assets', + '@assetsSource' => '@root/assets', + '@baseUrl' => '/', + '@public' => '@root/public', + '@runtime' => '@root/runtime', + '@vendor' => '@root/vendor', +]; diff --git a/config/common/bootstrap.php b/config/common/bootstrap.php new file mode 100644 index 0000000000000..b66d7068caa41 --- /dev/null +++ b/config/common/bootstrap.php @@ -0,0 +1,16 @@ + + */ +return [ + static function (ContainerInterface $container): void { + ConnectionProvider::set($container->get(ConnectionInterface::class)); + }, +]; diff --git a/config/common/di-providers.php b/config/common/di-providers.php new file mode 100644 index 0000000000000..746bf774625d0 --- /dev/null +++ b/config/common/di-providers.php @@ -0,0 +1,7 @@ + [ + '__construct()' => [ + 'traceLink' => $params['traceLink'] ?? null, + ], + ], +]; diff --git a/config/common/di/forms.php b/config/common/di/forms.php new file mode 100644 index 0000000000000..966515822596d --- /dev/null +++ b/config/common/di/forms.php @@ -0,0 +1,32 @@ + [ + '__construct()' => [ + 'hydrator' => DynamicReference::to([ + 'class' => Hydrator::class, + '__construct()' => [ + 'typeCaster' => new CompositeTypeCaster( + new NullTypeCaster(emptyString: true), + new PhpNativeTypeCaster(), + new NonArrayTypeCaster(), + new EnumTypeCaster(), + new HydratorTypeCaster(), + ), + ], + ]), + ], + ], +]; diff --git a/config/common/di/hydrator.php b/config/common/di/hydrator.php new file mode 100644 index 0000000000000..4ebd46f0dbaee --- /dev/null +++ b/config/common/di/hydrator.php @@ -0,0 +1,15 @@ + static fn() => new CompositeTypeCaster( + new PhpNativeTypeCaster(), + new HydratorTypeCaster(), + ), +]; diff --git a/config/common/di/logger.php b/config/common/di/logger.php new file mode 100644 index 0000000000000..4754a745ed239 --- /dev/null +++ b/config/common/di/logger.php @@ -0,0 +1,23 @@ + [ + 'class' => Logger::class, + '__construct()' => [ + 'targets' => ReferencesArray::from([ + FileTarget::class, + StreamTarget::class, + ]), + ], + ], +]; diff --git a/config/common/di/rbac.php b/config/common/di/rbac.php new file mode 100644 index 0000000000000..e96e092ecec16 --- /dev/null +++ b/config/common/di/rbac.php @@ -0,0 +1,22 @@ + [ + 'class' => Manager::class, + '__construct()' => [ + 'itemsStorage' => DynamicReference::to([ + 'class' => ItemsStorage::class, + '__construct()' => [dirname(__DIR__) . '/rbac-items.php'], + ]), + 'assignmentsStorage' => DynamicReference::to(AssignmentsStorage::class), + ], + ], +]; diff --git a/config/common/di/router.php b/config/common/di/router.php new file mode 100644 index 0000000000000..ba77532ee455a --- /dev/null +++ b/config/common/di/router.php @@ -0,0 +1,19 @@ + static fn() => new RouteCollection( + new RouteCollector()->addRoute( + Group::create('/api')->routes( + ...require(dirname(__DIR__, 2) . '/api/routes.php'), + ), + ...require(dirname(__DIR__, 2) . '/site/routes.php'), + ), + ), +]; diff --git a/config/common/params.php b/config/common/params.php new file mode 100644 index 0000000000000..fb2f42c3c8e52 --- /dev/null +++ b/config/common/params.php @@ -0,0 +1,10 @@ + [ + 'aliases' => require __DIR__ . '/aliases.php', + ], +]; diff --git a/config/common/rbac-items.php b/config/common/rbac-items.php new file mode 100644 index 0000000000000..ff9d5393293a3 --- /dev/null +++ b/config/common/rbac-items.php @@ -0,0 +1,36 @@ + Permission::UserManage->value, 'type' => 'permission'], + ['name' => Permission::DiaryManage->value, 'type' => 'permission'], + + /** + * Admin + */ + [ + 'name' => Role::Admin->value, + 'description' => Role::Admin->label(), + 'type' => 'role', + 'children' => [ + Permission::UserManage->value, + Permission::DiaryManage->value, + ], + ], + + /** + * Editor + */ + [ + 'name' => Role::Editor->value, + 'description' => Role::Editor->label(), + 'type' => 'role', + 'children' => [ + Permission::DiaryManage->value, + ], + ], +]; diff --git a/config/configuration.php b/config/configuration.php new file mode 100644 index 0000000000000..4df4e756a0068 --- /dev/null +++ b/config/configuration.php @@ -0,0 +1,82 @@ + [ + 'params' => 'common/params.php', + 'params-site' => [ + '$params', + '$params-web', + 'site/params.php', + ], + 'params-api' => [ + '$params', + '$params-web', + 'api/params.php', + ], + 'params-console' => [ + '$params', + 'console/params.php', + ], + 'di' => 'common/di/*.php', + 'di-site' => [ + '$di', + '$di-web', + 'site/di/*.php', + ], + 'di-api' => [ + '$di', + '$di-web', + 'api/di/*.php', + ], + 'di-console' => '$di', + 'di-delegates' => [], + 'di-delegates-site' => '$di-delegates', + 'di-delegates-api' => '$di-delegates', + 'di-delegates-console' => '$di-delegates', + 'di-providers' => 'common/di-providers.php', + 'di-providers-site' => '$di-providers', + 'di-providers-api' => '$di-providers', + 'di-providers-console' => '$di-providers', + 'events' => [], + 'events-site' => [ + '$events', + '$events-web', + ], + 'events-api' => [ + '$events', + '$events-web', + ], + 'events-console' => '$events', + 'routes' => 'common/routes.php', + 'bootstrap' => 'common/bootstrap.php', + 'bootstrap-site' => '$bootstrap', + 'bootstrap-api' => '$bootstrap', + 'bootstrap-console' => '$bootstrap', + 'widgets-site' => 'site/widgets.php', + ], + 'config-plugin-environments' => [ + Environment::DEV => [ + 'params' => [ + 'environments/dev/params.php', + ], + ], + Environment::TEST => [ + 'params' => [ + 'environments/test/params.php', + ], + ], + Environment::PROD => [ + 'params' => [ + 'environments/prod/params.php', + ], + ], + ], + 'config-plugin-options' => [ + 'source-directory' => 'config', + ], +]; diff --git a/config/console/commands.php b/config/console/commands.php new file mode 100644 index 0000000000000..9737feb45a63e --- /dev/null +++ b/config/console/commands.php @@ -0,0 +1,8 @@ + \App\UseCase\Users\CreateAdmin\CreateAdminCommand::class, +]; diff --git a/config/console/params.php b/config/console/params.php new file mode 100644 index 0000000000000..051a185934462 --- /dev/null +++ b/config/console/params.php @@ -0,0 +1,9 @@ + [ + 'commands' => require __DIR__ . '/commands.php', + ], +]; diff --git a/config/environments/dev/commands.php b/config/environments/dev/commands.php new file mode 100644 index 0000000000000..02d8cfa474ae1 --- /dev/null +++ b/config/environments/dev/commands.php @@ -0,0 +1,8 @@ + \App\UseCase\FakeData\FakeDataCommand::class, +]; diff --git a/config/environments/dev/params.php b/config/environments/dev/params.php new file mode 100644 index 0000000000000..f7a5bb28f02e2 --- /dev/null +++ b/config/environments/dev/params.php @@ -0,0 +1,11 @@ + 'phpstorm://open?url=file://{file}&line={line}', + + 'yiisoft/yii-console' => [ + 'commands' => require __DIR__ . '/commands.php', + ], +]; diff --git a/config/environments/prod/params.php b/config/environments/prod/params.php new file mode 100644 index 0000000000000..0dae23dee5e19 --- /dev/null +++ b/config/environments/prod/params.php @@ -0,0 +1,5 @@ + [ + '__construct()' => [ + 'dispatcher' => DynamicReference::to([ + 'class' => MiddlewareDispatcher::class, + 'withMiddlewares()' => [ + [ + ErrorCatcher::class, + static fn(ExceptionResponderFactory $factory) => $factory->create(), + SessionMiddleware::class, + CookieLoginMiddleware::class, + CsrfTokenMiddleware::class, + Router::class, + NotFoundMiddleware::class, + ], + ], + ]), + ], + ], + + ParametersResolverInterface::class => [ + 'class' => CompositeParametersResolver::class, + '__construct()' => [ + DynamicReference::to([ + 'class' => HydratorAttributeParametersResolver::class, + '__construct()' => [ + 'typeCaster' => DynamicReference::to( + static fn() => new CompositeTypeCaster( + new PhpNativeTypeCaster(), + new HydratorTypeCaster(), + ), + ), + ], + ]), + Reference::to(RequestInputParametersResolver::class), + ], + ], +]; diff --git a/config/site/di/psr17.php b/config/site/di/psr17.php new file mode 100644 index 0000000000000..9787bb293b3cd --- /dev/null +++ b/config/site/di/psr17.php @@ -0,0 +1,25 @@ + RequestFactory::class, + ServerRequestFactoryInterface::class => ServerRequestFactory::class, + ResponseFactoryInterface::class => ResponseFactory::class, + StreamFactoryInterface::class => StreamFactory::class, + UriFactoryInterface::class => UriFactory::class, + UploadedFileFactoryInterface::class => UploadedFileFactory::class, +]; diff --git a/config/site/di/user.php b/config/site/di/user.php new file mode 100644 index 0000000000000..1c0c2852a2646 --- /dev/null +++ b/config/site/di/user.php @@ -0,0 +1,19 @@ + [ + 'withSession()' => [Reference::to(SessionInterface::class)], + 'withAccessChecker()' => [Reference::to(ManagerInterface::class)], + ], + + IdentityRepositoryInterface::class => IdentityRepository::class, +]; diff --git a/config/site/di/view.php b/config/site/di/view.php new file mode 100644 index 0000000000000..842aad312ede2 --- /dev/null +++ b/config/site/di/view.php @@ -0,0 +1,39 @@ + [ + 'setParameters()' => [ + [ + 'assetManager' => Reference::to(AssetManager::class), + 'aliases' => Reference::to(Aliases::class), + 'urlGenerator' => Reference::to(UrlGenerator::class), + 'currentUser' => Reference::to(CurrentUser::class), + 'formatter' => Reference::to(Formatter::class), + ], + ], + ], + + WebViewRenderer::class => [ + '__construct()' => [ + 'layout' => Layout::MAIN, + 'injections' => [ + CsrfViewInjection::class, + ], + 'injectionContainer' => Reference::to(InjectionContainer::class), + ], + ], +]; diff --git a/config/site/form-bootstrap5-horizontal.php b/config/site/form-bootstrap5-horizontal.php new file mode 100644 index 0000000000000..d3280a867953b --- /dev/null +++ b/config/site/form-bootstrap5-horizontal.php @@ -0,0 +1,16 @@ + "{label}\n
{input}\n{hint}\n{error}
", + 'labelClass' => 'col-sm-3 col-form-label', + 'enrichFromValidationRules' => true, + 'validationRulesEnricher' => new ValidationRulesEnricher(), + ], +); diff --git a/config/site/form-bootstrap5-vertical.php b/config/site/form-bootstrap5-vertical.php new file mode 100644 index 0000000000000..487ce5b87bcd9 --- /dev/null +++ b/config/site/form-bootstrap5-vertical.php @@ -0,0 +1,14 @@ + true, + 'validationRulesEnricher' => new ValidationRulesEnricher(), + ], +); diff --git a/config/site/params.php b/config/site/params.php new file mode 100644 index 0000000000000..8d6d8803c53c2 --- /dev/null +++ b/config/site/params.php @@ -0,0 +1,24 @@ + [ + 'themes' => [ + FormTheme::VERTICAL => require __DIR__ . '/form-bootstrap5-vertical.php', + FormTheme::HORIZONTAL => require __DIR__ . '/form-bootstrap5-horizontal.php', + ], + 'defaultTheme' => FormTheme::HORIZONTAL, + ], + + 'yiisoft/widget' => [ + 'config' => [ + 'definitionsGroup' => 'widgets-site', + 'validate' => Environment::appDebug(), + ], + 'defaultTheme' => 'bootstrap5', + ], +]; diff --git a/config/site/routes.php b/config/site/routes.php new file mode 100644 index 0000000000000..9e3a6fefd063d --- /dev/null +++ b/config/site/routes.php @@ -0,0 +1,69 @@ +action(\App\UseCase\Home\Action::class)->name('home'), + + /** + * Diary + */ + Group::create() + ->middleware(CheckAccess::definition(Permission::DiaryManage)) + ->routes( + Route::get('/diary/manage')->action(\App\UseCase\Diary\Manage\Post\Listing\Action::class)->name('diary/manage/post/index'), + Route::methods(['GET', 'POST'], '/diary/manage/post/create')->action(\App\UseCase\Diary\Manage\Post\Create\Action::class)->name('diary/manage/post/create'), + Route::methods(['GET', 'POST'], '/diary/manage/post/update/{id}')->action(\App\UseCase\Diary\Manage\Post\Update\Action::class)->name('diary/manage/post/update'), + Route::methods(['GET', 'POST'], '/diary/manage/post/delete/{id}')->action(\App\UseCase\Diary\Manage\Post\Delete\Action::class)->name('diary/manage/post/delete'), + Route::get('/diary/manage/categories')->action(\App\UseCase\Diary\Manage\Category\Listing\Action::class)->name('diary/manage/category/index'), + Route::methods(['GET', 'POST'], '/diary/manage/category/create')->action(\App\UseCase\Diary\Manage\Category\Create\Action::class)->name('diary/manage/category/create'), + Route::methods(['GET', 'POST'], '/diary/manage/category/update/{id}')->action(\App\UseCase\Diary\Manage\Category\Update\Action::class)->name('diary/manage/category/update'), + Route::methods(['GET', 'POST'], '/diary/manage/category/delete/{id}')->action(\App\UseCase\Diary\Manage\Category\Delete\Action::class)->name('diary/manage/category/delete'), + ), + Route::get('/diary/category/{slug}[/{page}]')->action(\App\UseCase\Diary\Front\Category\Action::class)->name('diary/category/index'), + Route::get('/diary/post/{slug}')->action(\App\UseCase\Diary\Front\Post\Action::class)->name('diary/post/view'), + Route::get('/diary[/{page}]')->action(\App\UseCase\Diary\Front\Listing\Action::class)->name('diary/post/index'), + + /** + * Users + */ + Group::create() + ->middleware(CheckAccess::definition(Permission::UserManage)) + ->routes( + Route::get('/users')->action(\App\UseCase\Users\List\Action::class)->name('user/index'), + Route::methods(['GET', 'POST'], '/users/create') + ->action(\App\UseCase\Users\Create\Action::class) + ->name('user/create'), + Route::methods(['GET', 'POST'], '/users/update/{id}') + ->action(\App\UseCase\Users\Update\Action::class) + ->name('user/update'), + Route::methods(['GET', 'POST'], '/users/change-password/{id}') + ->action(\App\UseCase\Users\ChangePassword\Action::class) + ->name('user/change-password'), + Route::methods(['GET', 'POST'], '/users/delete/{id}') + ->action(\App\UseCase\Users\Delete\Action::class) + ->name('user/delete'), + ), + + /** + * Current user + */ + Route::methods(['GET', 'POST'], '/login')->action(\App\UseCase\Login\Action::class)->name('login'), + Group::create() + ->middleware(Authentication::class) + ->routes( + Route::post('/logout')->action(\App\UseCase\Logout\Action::class)->name('logout'), + Route::methods(['GET', 'POST'], '/profile/change-password') + ->action(\App\UseCase\Profile\ChangePassword\Action::class) + ->name('profile/change-password'), + Route::methods(['GET', 'POST'], '/profile/update') + ->action(\App\UseCase\Profile\UpdateProfile\Action::class) + ->name('profile/update'), + ), +]; diff --git a/config/site/widgets.php b/config/site/widgets.php new file mode 100644 index 0000000000000..e5c747f073e6b --- /dev/null +++ b/config/site/widgets.php @@ -0,0 +1,20 @@ + [ + 'urlParameterProvider()' => [ + Reference::to(UrlParameterProvider::class), + ], + 'urlCreator()' => [ + Reference::to(UrlCreator::class), + ], + 'ignoreMissingPage()' => [true], + ], +]; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000..9e796d907d275 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +services: + app: + build: . + user: ${UID}:${GID} + environment: + COMPOSER_CACHE_DIR: /app/runtime/cache/composer + volumes: + - .:/app + ports: + - "8080:8080" + command: php ./yii serve 0.0.0.0 diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000000000..e95e8caf03177 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + diff --git a/public/assets/.gitignore b/public/assets/.gitignore new file mode 100755 index 0000000000000..d6b7ef32c8478 --- /dev/null +++ b/public/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000..8535d2245629f Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000000000..7046d66f447c0 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000000000..2f958c2c14679 --- /dev/null +++ b/public/index.php @@ -0,0 +1,99 @@ +setLevels([ + LogLevel::EMERGENCY, + LogLevel::ERROR, + LogLevel::WARNING, + ]), + ], + ), + new JsonRenderer(), + ), + )->run(); +} +new HttpApplicationRunner( + rootPath: $root, + debug: Environment::appDebug(), + checkEvents: Environment::appDebug(), + environment: Environment::appEnv(), + bootstrapGroup: 'bootstrap-site', + eventsGroup: 'events-site', + diGroup: 'di-site', + diProvidersGroup: 'di-providers-site', + diDelegatesGroup: 'di-delegates-site', + diTagsGroup: 'di-tags-site', + paramsGroup: 'params-site', + nestedParamsGroups: ['params', 'params-web'], + nestedEventsGroups: ['events', 'events-web'], + temporaryErrorHandler: new ErrorHandler( + new Logger( + [ + new FileTarget($root . '/runtime/logs/site-container-building.log') + ->setLevels([ + LogLevel::EMERGENCY, + LogLevel::ERROR, + LogLevel::WARNING, + ]), + ], + ), + new HtmlRenderer(), + ), +)->run(); diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000000..6f27bb66a3469 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: \ No newline at end of file diff --git a/rector.php b/rector.php new file mode 100644 index 0000000000000..e3d1868e59827 --- /dev/null +++ b/rector.php @@ -0,0 +1,30 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withPhpSets(php85: true) + ->withRules([ + InlineConstructorDefaultToPropertyRector::class, + ]) + ->withSkipPath('tests/Support/_generated') + ->withSkip([ + ClassPropertyAssignToConstructorPromotionRector::class, + InlineConstructorDefaultToPropertyRector::class, + ClosureToArrowFunctionRector::class, + ReadOnlyPropertyRector::class, + AddOverrideAttributeToOverriddenMethodsRector::class, + AddOverrideAttributeToOverriddenPropertiesRector::class, + ]); diff --git a/runtime/.gitignore b/runtime/.gitignore new file mode 100755 index 0000000000000..d6b7ef32c8478 --- /dev/null +++ b/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/Domain/Category/Category.php b/src/Domain/Category/Category.php new file mode 100644 index 0000000000000..092338b78a9db --- /dev/null +++ b/src/Domain/Category/Category.php @@ -0,0 +1,44 @@ +id ?? throw new LogicException('ID is not set.'); + } + + public function tableName(): string + { + return '{{%category}}'; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'posts' => $this + ->hasMany(Post::class, ['id' => 'post_id']) + ->viaTable('post_category', ['category_id' => 'id']), + default => parent::relationQuery($name), + }; + } +} diff --git a/src/Domain/Post/Post.php b/src/Domain/Post/Post.php new file mode 100644 index 0000000000000..f5e45be5bf77b --- /dev/null +++ b/src/Domain/Post/Post.php @@ -0,0 +1,96 @@ +id ?? throw new LogicException('ID is not set.'); + } + + /** + * @return Category[] + */ + public function getCategories(): array + { + /** @var Category[] */ + return $this->relationQuery('categories')->all(); + } + + public function getCreatedByUser(): User + { + /** @var User */ + return $this->relation('createdBy'); + } + + public function getUpdatedByUser(): User + { + /** @var User */ + return $this->relation('updatedBy'); + } + + public function tableName(): string + { + return '{{%post}}'; + } + + public static function publicQuery(): ActiveQueryInterface + { + return self::query() + ->where(['status' => PostStatus::Published]) + ->andWhere(['<=', 'publication_date', new Expression('CURRENT_TIMESTAMP')]) + ->orderBy(['publication_date' => SORT_DESC]); + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'categories' => $this + ->hasMany(Category::class, ['id' => 'category_id']) + ->viaTable('post_category', ['post_id' => 'id']), + 'createdBy' => $this->hasOne(User::class, ['id' => 'created_by']), + 'updatedBy' => $this->hasOne(User::class, ['id' => 'updated_by']), + default => parent::relationQuery($name), + }; + } + + protected function populateProperty(string $name, mixed $value): void + { + switch ($name) { + case 'status': + $this->status = PostStatus::from((int) $value); + break; + + default: + parent::populateProperty($name, $value); + } + } +} diff --git a/src/Domain/Post/PostStatus.php b/src/Domain/Post/PostStatus.php new file mode 100644 index 0000000000000..8e5fc757388f2 --- /dev/null +++ b/src/Domain/Post/PostStatus.php @@ -0,0 +1,33 @@ + 'Draft', + self::Published => 'Published', + self::Archived => 'Archived', + }; + } + + /** + * @return array + */ + public static function labelsByValue(): array + { + $result = []; + foreach (self::cases() as $type) { + $result[$type->value] = $type->label(); + } + return $result; + } +} diff --git a/src/Domain/User/AuthKeyGenerator.php b/src/Domain/User/AuthKeyGenerator.php new file mode 100644 index 0000000000000..44427176a38f0 --- /dev/null +++ b/src/Domain/User/AuthKeyGenerator.php @@ -0,0 +1,40 @@ +length) . '~' . time(); + } + + public function validate(string $key, string $originKey): bool + { + if ($key !== $originKey) { + return false; + } + + $parts = explode('~', $key); + if (count($parts) !== 2) { + return false; + } + + if ((time() - $this->duration) > (int) $parts[1]) { + return false; + } + + return true; + } +} diff --git a/src/Domain/User/User.php b/src/Domain/User/User.php new file mode 100644 index 0000000000000..c07a54f657b21 --- /dev/null +++ b/src/Domain/User/User.php @@ -0,0 +1,64 @@ +id ?? throw new LogicException('ID is not set.'); + } + + public function canSignIn(): bool + { + return $this->status === UserStatus::Active; + } + + public function tableName(): string + { + return '{{%user}}'; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'postsCreatedBy' => $this->hasMany(Post::class, ['created_by' => 'id']), + 'postsUpdatedBy' => $this->hasMany(Post::class, ['updated_by' => 'id']), + default => parent::relationQuery($name), + }; + } + + protected function populateProperty(string $name, mixed $value): void + { + switch ($name) { + case 'status': + $this->status = UserStatus::from((int) $value); + break; + + default: + parent::populateProperty($name, $value); + } + } +} diff --git a/src/Domain/User/UserStatus.php b/src/Domain/User/UserStatus.php new file mode 100644 index 0000000000000..6600ae012e486 --- /dev/null +++ b/src/Domain/User/UserStatus.php @@ -0,0 +1,31 @@ + 'Inactive', + self::Active => 'Active', + }; + } + + /** + * @return array + */ + public static function labelsByValue(): array + { + $result = []; + foreach (self::cases() as $type) { + $result[$type->value] = $type->label(); + } + return $result; + } +} diff --git a/src/Environment.php b/src/Environment.php new file mode 100644 index 0000000000000..047ae83956c6a --- /dev/null +++ b/src/Environment.php @@ -0,0 +1,137 @@ + static fn(Aliases $aliases) => new Connection( + new Driver( + new Dsn(databaseName: $aliases->get('@runtime/db.sqlite')), + ), + new SchemaCache( + new FileCache($aliases->get('@runtime/cache/db')), + ), + ), + + MigrationService::class => [ + 'setNewMigrationNamespace()' => ['App\\Migration'], + 'setSourceNamespaces()' => [['App\\Migration']], + 'setSourcePaths()' => [[ + dirname(__DIR__, 2) . '/vendor/yiisoft/rbac-db/migrations/assignments', + ]], + ], + ]; + } + + public function getExtensions(): array + { + return []; + } +} diff --git a/src/Migration/M250907191044CreateUserTable.php b/src/Migration/M250907191044CreateUserTable.php new file mode 100644 index 0000000000000..729fd388b1bfc --- /dev/null +++ b/src/Migration/M250907191044CreateUserTable.php @@ -0,0 +1,29 @@ +columnBuilder(); + $b->createTable('user', [ + 'id' => $cb::primaryKey(), + 'login' => $cb::string(50)->notNull()->unique(), + 'name' => $cb::string(100)->notNull(), + 'status' => $cb::tinyint()->notNull(), + 'password_hash' => $cb::string()->notNull(), + 'auth_key' => $cb::string(75)->notNull(), + ]); + } + + public function down(MigrationBuilder $b): void + { + $b->dropTable('user'); + } +} diff --git a/src/Migration/M250913084053CreateDiaryTables.php b/src/Migration/M250913084053CreateDiaryTables.php new file mode 100644 index 0000000000000..e1c5b6f1d48cd --- /dev/null +++ b/src/Migration/M250913084053CreateDiaryTables.php @@ -0,0 +1,45 @@ +columnBuilder(); + $b->createTable('post', [ + 'id' => $cb::primaryKey(), + 'status' => $cb::tinyint()->notNull(), + 'title' => $cb::string(255)->notNull(), + 'body' => $cb::text()->notNull(), + 'slug' => $cb::string(255)->notNull()->unique(), + 'publication_date' => $cb::dateTime()->null(), + 'created_at' => $cb::dateTime()->notNull(), + 'created_by' => $cb::integer()->notNull(), + 'updated_at' => $cb::dateTime()->notNull(), + 'updated_by' => $cb::integer()->notNull(), + ]); + $b->createTable('category', [ + 'id' => $cb::primaryKey(), + 'name' => $cb::string(100)->notNull(), + 'desc' => $cb::text()->notNull(), + 'slug' => $cb::string(100)->notNull()->unique(), + ]); + $b->createTable('post_category', [ + 'post_id' => $cb::integer()->notNull(), + 'category_id' => $cb::integer()->notNull(), + ]); + } + + public function down(MigrationBuilder $b): void + { + $b->dropTable('post_category'); + $b->dropTable('category'); + $b->dropTable('post'); + } +} diff --git a/src/Presentation/Api/ResponseFactory/ExceptionResponderFactory.php b/src/Presentation/Api/ResponseFactory/ExceptionResponderFactory.php new file mode 100644 index 0000000000000..fb59aeea22757 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/ExceptionResponderFactory.php @@ -0,0 +1,53 @@ + $this->inputValidationException(...), + Throwable::class => $this->throwable(...), + ], + $this->psrResponseFactory, + $this->injector, + ); + } + + private function inputValidationException(InputValidationException $exception): ResponseInterface + { + return $this->apiResponseFactory->failValidation($exception->getResult()); + } + + private function throwable(Throwable $exception): ResponseInterface + { + if (UserException::isUserException($exception)) { + $code = $exception->getCode(); + return $this->apiResponseFactory->fail( + $exception->getMessage(), + code: is_int($code) ? $code : null, + ); + } + throw $exception; + } +} diff --git a/src/Presentation/Api/ResponseFactory/NotFoundMiddleware.php b/src/Presentation/Api/ResponseFactory/NotFoundMiddleware.php new file mode 100644 index 0000000000000..0d4f6b8a975bc --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/NotFoundMiddleware.php @@ -0,0 +1,22 @@ +responseFactory->notFound(); + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/AsIsPresenter.php b/src/Presentation/Api/ResponseFactory/Presenter/AsIsPresenter.php new file mode 100644 index 0000000000000..cab62c0d73ec0 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/AsIsPresenter.php @@ -0,0 +1,16 @@ + + */ +final readonly class AsIsPresenter implements PresenterInterface +{ + public function present(mixed $value): mixed + { + return $value; + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/CollectionPresenter.php b/src/Presentation/Api/ResponseFactory/Presenter/CollectionPresenter.php new file mode 100644 index 0000000000000..8fe9a72d93072 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/CollectionPresenter.php @@ -0,0 +1,24 @@ + + */ +final readonly class CollectionPresenter implements PresenterInterface +{ + public function __construct( + private PresenterInterface $itemPresenter = new AsIsPresenter(), + ) {} + + public function present(mixed $value): array + { + $result = []; + foreach ($value as $item) { + $result[] = $this->itemPresenter->present($item); + } + return $result; + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/FailPresenter.php b/src/Presentation/Api/ResponseFactory/Presenter/FailPresenter.php new file mode 100644 index 0000000000000..dc8bff5bae93d --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/FailPresenter.php @@ -0,0 +1,32 @@ + + */ +final readonly class FailPresenter implements PresenterInterface +{ + public function __construct( + private string $message = 'Unknown error.', + private ?int $code = null, + private PresenterInterface $presenter = new AsIsPresenter(), + ) {} + + public function present(mixed $value): mixed + { + $result = [ + 'status' => 'failed', + 'error_message' => $this->message, + ]; + if ($this->code !== null) { + $result['error_code'] = $this->code; + } + if ($value !== null) { + $result['error_data'] = $this->presenter->present($value); + } + return $result; + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/OffsetPaginatorPresenter.php b/src/Presentation/Api/ResponseFactory/Presenter/OffsetPaginatorPresenter.php new file mode 100644 index 0000000000000..00ab1145843e8 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/OffsetPaginatorPresenter.php @@ -0,0 +1,31 @@ + + */ +final readonly class OffsetPaginatorPresenter implements PresenterInterface +{ + private CollectionPresenter $collectionPresenter; + + public function __construct( + PresenterInterface $itemPresenter = new AsIsPresenter(), + ) { + $this->collectionPresenter = new CollectionPresenter($itemPresenter); + } + + public function present(mixed $value): array + { + return [ + 'items' => $this->collectionPresenter->present($value->read()), + 'page_size' => $value->getPageSize(), + 'current_page' => $value->getCurrentPage(), + 'total_pages' => $value->getTotalPages(), + ]; + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/PresenterInterface.php b/src/Presentation/Api/ResponseFactory/Presenter/PresenterInterface.php new file mode 100644 index 0000000000000..ad4e8498de69f --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/PresenterInterface.php @@ -0,0 +1,16 @@ + + */ +final readonly class SuccessPresenter implements PresenterInterface +{ + public function __construct( + private PresenterInterface $presenter = new AsIsPresenter(), + ) {} + + public function present(mixed $value): array + { + return [ + 'status' => 'success', + 'data' => $this->presenter->present($value), + ]; + } +} diff --git a/src/Presentation/Api/ResponseFactory/Presenter/ValidationResultPresenter.php b/src/Presentation/Api/ResponseFactory/Presenter/ValidationResultPresenter.php new file mode 100644 index 0000000000000..63c4f0ab1b2d2 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/Presenter/ValidationResultPresenter.php @@ -0,0 +1,18 @@ + + */ +final readonly class ValidationResultPresenter implements PresenterInterface +{ + public function present(mixed $value): array + { + return $value->getErrorMessagesIndexedByPath(); + } +} diff --git a/src/Presentation/Api/ResponseFactory/ResponseFactory.php b/src/Presentation/Api/ResponseFactory/ResponseFactory.php new file mode 100644 index 0000000000000..d9c4970a13285 --- /dev/null +++ b/src/Presentation/Api/ResponseFactory/ResponseFactory.php @@ -0,0 +1,60 @@ +dataResponseFactory->createResponse( + new SuccessPresenter($presenter)->present($data), + ); + } + + public function fail( + string $message, + array|object|null $data = null, + ?int $code = null, + int $httpCode = Status::BAD_REQUEST, + PresenterInterface $presenter = new AsIsPresenter(), + ): ResponseInterface { + return $this->dataResponseFactory + ->createResponse( + new FailPresenter($message, $code, $presenter)->present($data), + ) + ->withStatus($httpCode); + } + + public function notFound(string $message = 'Not found.'): ResponseInterface + { + return $this->fail($message, httpCode: Status::NOT_FOUND); + } + + public function failValidation(Result $result): ResponseInterface + { + return $this->fail( + 'Validation failed.', + $result, + httpCode: Status::UNPROCESSABLE_ENTITY, + presenter: new ValidationResultPresenter(), + ); + } +} diff --git a/src/Presentation/Site/Access/CheckAccess.php b/src/Presentation/Site/Access/CheckAccess.php new file mode 100644 index 0000000000000..edf86797536ea --- /dev/null +++ b/src/Presentation/Site/Access/CheckAccess.php @@ -0,0 +1,45 @@ + + */ + public static function definition(Permission $permission, array $params = []): array + { + return [ + 'class' => self::class, + '__construct()' => [ + 'permissionName' => $permission->value, + 'params' => $params, + ], + ]; + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ($this->currentUser->can($this->permissionName, $this->params)) { + return $handler->handle($request); + } + + return $this->responseFactory->accessDenied(); + } +} diff --git a/src/Presentation/Site/Access/Permission.php b/src/Presentation/Site/Access/Permission.php new file mode 100644 index 0000000000000..7eef6411d5388 --- /dev/null +++ b/src/Presentation/Site/Access/Permission.php @@ -0,0 +1,11 @@ + 'Administrator', + self::Editor => 'Editor', + }; + } + + /** + * @return array + */ + public static function labelsByValue(): array + { + $result = []; + foreach (self::cases() as $type) { + $result[$type->value] = $type->label(); + } + return $result; + } +} diff --git a/src/Presentation/Site/Identity/AuthenticatedUserProvider.php b/src/Presentation/Site/Identity/AuthenticatedUserProvider.php new file mode 100644 index 0000000000000..db05e387690e9 --- /dev/null +++ b/src/Presentation/Site/Identity/AuthenticatedUserProvider.php @@ -0,0 +1,25 @@ +currentUser->getId(); + if ($rawId === null) { + throw new LogicException('User is not authenticated.'); + } + + return (int) $rawId; + } +} diff --git a/src/Presentation/Site/Identity/IdentityRepository.php b/src/Presentation/Site/Identity/IdentityRepository.php new file mode 100644 index 0000000000000..d23ce2907de5f --- /dev/null +++ b/src/Presentation/Site/Identity/IdentityRepository.php @@ -0,0 +1,28 @@ +findByPk($id); + if ($user === null || !$user->canSignIn()) { + return null; + } + + return new UserIdentity($user, $this->authKeyGenerator); + } +} diff --git a/src/Presentation/Site/Identity/UserIdentity.php b/src/Presentation/Site/Identity/UserIdentity.php new file mode 100644 index 0000000000000..7ca49e0961552 --- /dev/null +++ b/src/Presentation/Site/Identity/UserIdentity.php @@ -0,0 +1,32 @@ +user->getId(); + } + + public function getCookieLoginKey(): string + { + return $this->user->auth_key; + } + + public function validateCookieLoginKey(string $key): bool + { + return $this->authKeyGenerator->validate($key, $this->user->auth_key); + } +} diff --git a/src/Presentation/Site/Layout/BootstrapAsset.php b/src/Presentation/Site/Layout/BootstrapAsset.php new file mode 100644 index 0000000000000..5f9cb4f0c3417 --- /dev/null +++ b/src/Presentation/Site/Layout/BootstrapAsset.php @@ -0,0 +1,19 @@ + $urlParameters + */ + public function __construct( + public string|Stringable $label, + public ?string $customUrl = null, + public ?string $urlName = null, + public array $urlParameters = [], + ) {} +} diff --git a/src/Presentation/Site/Layout/Breadcrumbs/Breadcrumbs.php b/src/Presentation/Site/Layout/Breadcrumbs/Breadcrumbs.php new file mode 100644 index 0000000000000..d2b77a1b20f88 --- /dev/null +++ b/src/Presentation/Site/Layout/Breadcrumbs/Breadcrumbs.php @@ -0,0 +1,66 @@ + $breadcrumbs + */ + public function __construct( + private readonly UrlGenerator $urlGenerator, + private readonly array $breadcrumbs, + ) {} + + public function render(): string + { + $items = []; + foreach ($this->breadcrumbs as $breadcrumb) { + $items[] = [ + 'label' => $breadcrumb->label, + 'url' => $this->generateUrl($breadcrumb), + ]; + } + + if ($items === []) { + return ''; + } + + array_unshift( + $items, + [ + 'label' => 'Home', + 'url' => $this->urlGenerator->home(), + ], + ); + + $html = ''; + + return $html; + } + + private function generateUrl(Breadcrumb $breadcrumb): ?string + { + if ($breadcrumb->customUrl !== null) { + return $breadcrumb->customUrl; + } + + return $breadcrumb->urlName === null + ? null + : $this->urlGenerator->generate($breadcrumb->urlName, $breadcrumb->urlParameters); + } +} diff --git a/src/Presentation/Site/Layout/ContentNotices/ContentNotices.php b/src/Presentation/Site/Layout/ContentNotices/ContentNotices.php new file mode 100644 index 0000000000000..df75a2aac769d --- /dev/null +++ b/src/Presentation/Site/Layout/ContentNotices/ContentNotices.php @@ -0,0 +1,58 @@ +flash->add(self::KEY, [Type::Success->value, $message]); + } + + public function error(string $message): void + { + $this->flash->add(self::KEY, [Type::Error->value, $message]); + } + + /** + * @return list + */ + public function get(): array + { + $rows = $this->flash->get(self::KEY); + if (!is_array($rows)) { + return []; + } + + $notices = []; + foreach ($rows as $row) { + if ( + !is_array($row) + || array_keys($row) !== [0, 1] + || !is_int($row[0]) + || !is_string($row[1]) + || $row[1] === '' + || ($type = Type::tryFrom($row[0])) === null + ) { + continue; + } + $notices[] = new Notice($type, $row[1]); + } + + return $notices; + } +} diff --git a/src/Presentation/Site/Layout/ContentNotices/ContentNoticesWidget.php b/src/Presentation/Site/Layout/ContentNotices/ContentNoticesWidget.php new file mode 100644 index 0000000000000..b5f9f76ced761 --- /dev/null +++ b/src/Presentation/Site/Layout/ContentNotices/ContentNoticesWidget.php @@ -0,0 +1,38 @@ +contentNotices->get(); + if ($notices === []) { + return ''; + } + + $html = []; + foreach ($notices as $notice) { + $html[] = Html::div() + ->class('alert alert-dismissible fade show', $notice->type->class()) + ->content( + NoEncode::string( + '', + ), + $notice->message, + ); + } + + return '
' . implode('', $html) . '
'; + } +} diff --git a/src/Presentation/Site/Layout/ContentNotices/Notice.php b/src/Presentation/Site/Layout/ContentNotices/Notice.php new file mode 100644 index 0000000000000..81781348b1bad --- /dev/null +++ b/src/Presentation/Site/Layout/ContentNotices/Notice.php @@ -0,0 +1,13 @@ + 'alert-success', + self::Error => 'alert-danger', + }; + } +} diff --git a/src/Presentation/Site/Layout/Form/FormTheme.php b/src/Presentation/Site/Layout/Form/FormTheme.php new file mode 100644 index 0000000000000..ab3ca6105a673 --- /dev/null +++ b/src/Presentation/Site/Layout/Form/FormTheme.php @@ -0,0 +1,11 @@ + 'sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz', + 'crossorigin' => 'anonymous', + ]; +} diff --git a/src/Presentation/Site/Layout/Layout.php b/src/Presentation/Site/Layout/Layout.php new file mode 100644 index 0000000000000..b547cd60f2697 --- /dev/null +++ b/src/Presentation/Site/Layout/Layout.php @@ -0,0 +1,12 @@ + $urlParameters + */ + public function __construct( + public string $label, + public ?string $urlName = null, + public array $urlParameters = [], + public ?string $customUrl = null, + public ?Permission $permission = null, + public ?Closure $activeCallback = null, + ) {} +} diff --git a/src/Presentation/Site/Layout/Menu/ItemHandler.php b/src/Presentation/Site/Layout/Menu/ItemHandler.php new file mode 100644 index 0000000000000..702f6c28db498 --- /dev/null +++ b/src/Presentation/Site/Layout/Menu/ItemHandler.php @@ -0,0 +1,56 @@ +permission !== null && !$this->currentUser->can($item->permission)) { + return null; + } + + return new HandledItem( + label: $item->label, + url: $this->generateUrl($item), + active: $this->shouldBeActive($item), + ); + } + + private function generateUrl(Item $item): ?string + { + if ($item->customUrl !== null) { + return $item->customUrl; + } + + if ($item->urlName === null) { + return null; + } + + return $this->urlGenerator->generate($item->urlName, $item->urlParameters); + } + + private function shouldBeActive(Item $item): bool + { + if ($item->activeCallback !== null) { + return (bool) $this->injector->invoke($item->activeCallback); + } + + return $item->urlName !== null + && $this->currentRoute->getName() === $item->urlName; + } +} diff --git a/src/Presentation/Site/Layout/Menu/MainMenu.php b/src/Presentation/Site/Layout/Menu/MainMenu.php new file mode 100644 index 0000000000000..1e60e14b94abf --- /dev/null +++ b/src/Presentation/Site/Layout/Menu/MainMenu.php @@ -0,0 +1,47 @@ + $items + */ + public function __construct( + private readonly ItemHandler $itemHandler, + private readonly array $items, + ) {} + + public function render(): string + { + $li = []; + foreach ($this->items as $item) { + $item = $this->itemHandler->handle($item); + if ($item === null) { + continue; + } + $li[] = Html::li( + $item->url === null ? $item->label + : Html::a( + $item->label, + $item->url, + [ + 'class' => [ + 'nav-link px-2', + $item->active ? 'active' : 'link-secondary', + ], + ], + ), + ); + } + + return (string) Html::ul() + ->class('nav nav-pills col-12 col-md-auto mb-2 justify-content-center mb-md-0') + ->items(...$li); + } +} diff --git a/src/Presentation/Site/Layout/layout-error.php b/src/Presentation/Site/Layout/layout-error.php new file mode 100644 index 0000000000000..9947bd1ae7dd1 --- /dev/null +++ b/src/Presentation/Site/Layout/layout-error.php @@ -0,0 +1,43 @@ +register(MainAsset::class); + +$this->addCssFiles($assetManager->getCssFiles()); +$this->addCssStrings($assetManager->getCssStrings()); +$this->addJsFiles($assetManager->getJsFiles()); +$this->addJsStrings($assetManager->getJsStrings()); +$this->addJsVars($assetManager->getJsVars()); + +$this->beginPage(); +?> + + + + + + + getTitle()) ?> + head() ?> + + +beginBody() ?> +
+ +
+endBody() ?> + + +endPage() ?> diff --git a/src/Presentation/Site/Layout/layout-main.php b/src/Presentation/Site/Layout/layout-main.php new file mode 100644 index 0000000000000..00bd7df41eb00 --- /dev/null +++ b/src/Presentation/Site/Layout/layout-main.php @@ -0,0 +1,137 @@ +register(MainAsset::class); + +$this->addCssFiles($assetManager->getCssFiles()); +$this->addCssStrings($assetManager->getCssStrings()); +$this->addJsFiles($assetManager->getJsFiles()); +$this->addJsStrings($assetManager->getJsStrings()); +$this->addJsVars($assetManager->getJsVars()); + +$this->beginPage() +?> + + + + + + + getTitle()) ?> + head() ?> + + +beginBody() ?> +
+
+ + [ + new Item('Home', urlName: 'home'), + new Item( + 'Diary', + urlName: 'diary/post/index', + activeCallback: static fn(CurrentRoute $currentRoute) => str_starts_with($currentRoute->getName() ?? '', 'diary/'), + ), + new Item( + 'Users', + urlName: 'user/index', + permission: Permission::UserManage, + activeCallback: static fn(CurrentRoute $currentRoute) => str_starts_with($currentRoute->getName() ?? '', 'user/'), + ), + ], + ]) ?> +
+ isGuest()) { ?> + login(), ['class' => 'btn btn-outline-primary me-2']) ?> + + getIdentity(); + ?> + + user->name) ?> + + + +
+
+ $this->getParameter('breadcrumbs', []), + ]) ?> + +
+
+ +
+
+
+
+ Yii3 Demo Diary +
+ +
+
+endBody() ?> + + +endPage() ?> diff --git a/src/Presentation/Site/Layout/layout-pure.php b/src/Presentation/Site/Layout/layout-pure.php new file mode 100644 index 0000000000000..e87558d372b65 --- /dev/null +++ b/src/Presentation/Site/Layout/layout-pure.php @@ -0,0 +1,44 @@ +register(MainAsset::class); + +$this->addCssFiles($assetManager->getCssFiles()); +$this->addCssStrings($assetManager->getCssStrings()); +$this->addJsFiles($assetManager->getJsFiles()); +$this->addJsStrings($assetManager->getJsStrings()); +$this->addJsVars($assetManager->getJsVars()); + +$htmlAttributes = ['class' => $this->getParameter('htmlClass', null)]; +$bodyAttributes = ['class' => $this->getParameter('bodyClass', null)]; + +$this->beginPage(); +?> + + + + + + + getTitle()) ?> + head() ?> + + +beginBody() ?> + +endBody() ?> + + +endPage() ?> diff --git a/src/Presentation/Site/ResponseFactory/ExceptionResponderFactory.php b/src/Presentation/Site/ResponseFactory/ExceptionResponderFactory.php new file mode 100644 index 0000000000000..09760318abebd --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/ExceptionResponderFactory.php @@ -0,0 +1,57 @@ + $this->pageNotFound(...), + Throwable::class => $this->throwable(...), + ], + $this->psrResponseFactory, + $this->injector, + ); + } + + private function pageNotFound(PageNotFoundException $exception): ResponseInterface + { + return $this->siteResponseFactory->notFound( + $exception->title, + $exception->description, + ); + } + + private function throwable(Throwable $exception): ResponseInterface + { + if (UserException::isUserException($exception)) { + return $this->siteResponseFactory + ->render( + __DIR__ . '/user-exception.php', + ['message' => $exception->getMessage()], + Layout::ERROR, + ) + ->withStatus(Status::OK); + } + throw $exception; + } +} diff --git a/src/Presentation/Site/ResponseFactory/NotFoundMiddleware.php b/src/Presentation/Site/ResponseFactory/NotFoundMiddleware.php new file mode 100644 index 0000000000000..34eb165ae73df --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/NotFoundMiddleware.php @@ -0,0 +1,22 @@ +responseFactory->notFound(); + } +} diff --git a/src/Presentation/Site/ResponseFactory/PageNotFoundException.php b/src/Presentation/Site/ResponseFactory/PageNotFoundException.php new file mode 100644 index 0000000000000..ad084a511fa22 --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/PageNotFoundException.php @@ -0,0 +1,17 @@ +responseFactory->createResponse($code, $reasonPhrase); + } + + public function createHtmlResponse( + mixed $data = null, + int $code = Status::OK, + string $reasonPhrase = '', + ): ResponseInterface { + return $this->htmlResponseFactory->createResponse($data, $code, $reasonPhrase); + } + + public function temporarilyRedirect(string $url, ?ResponseInterface $response = null): ResponseInterface + { + return ($response ?? $this->createResponse()) + ->withStatus(Status::FOUND) + ->withHeader('Location', $url); + } + + public function notFound(string $title = 'Page not found', string $description = ''): ResponseInterface + { + return $this->viewRenderer + ->withLayout(Layout::ERROR) + ->render(__DIR__ . '/not-found.php', ['title' => $title, 'description' => $description]) + ->withStatus(Status::NOT_FOUND); + } + + public function accessDenied(): ResponseInterface + { + return $this->viewRenderer + ->withLayout(Layout::ERROR) + ->render(__DIR__ . '/access-denied.php') + ->withStatus(Status::FORBIDDEN); + } + + /** + * @param array $parameters + */ + public function render(string $view, array $parameters = [], string $layout = Layout::MAIN): ResponseInterface + { + return $this->viewRenderer->withLayout($layout)->render($view, $parameters); + } +} diff --git a/src/Presentation/Site/ResponseFactory/UserExceptionMiddleware.php b/src/Presentation/Site/ResponseFactory/UserExceptionMiddleware.php new file mode 100644 index 0000000000000..771b201ef6df2 --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/UserExceptionMiddleware.php @@ -0,0 +1,47 @@ +handle($request); + } catch (Throwable $exception) { + if (UserException::isUserException($exception)) { + return $this->handleUserException($exception, $request); + } + throw $exception; + } + } + + public function handleUserException(Throwable $exception, ServerRequestInterface $request): ResponseInterface + { + return $this->responseFactory + ->render( + __DIR__ . '/user-exception.php', + ['message' => $exception->getMessage()], + Layout::ERROR, + ) + ->withStatus(Status::OK); + } +} diff --git a/src/Presentation/Site/ResponseFactory/access-denied.php b/src/Presentation/Site/ResponseFactory/access-denied.php new file mode 100644 index 0000000000000..f10502dc6aa3e --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/access-denied.php @@ -0,0 +1,22 @@ +setTitle('Access Denied'); +?> +
+

Access Denied

+

+ Go Home +

+
diff --git a/src/Presentation/Site/ResponseFactory/not-found.php b/src/Presentation/Site/ResponseFactory/not-found.php new file mode 100644 index 0000000000000..88cdd20fb0077 --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/not-found.php @@ -0,0 +1,32 @@ +setTitle('404'); +?> +
+

+ +

+ +

+ Go Back Home +

+
diff --git a/src/Presentation/Site/ResponseFactory/user-exception.php b/src/Presentation/Site/ResponseFactory/user-exception.php new file mode 100644 index 0000000000000..2f93d55a7ad7c --- /dev/null +++ b/src/Presentation/Site/ResponseFactory/user-exception.php @@ -0,0 +1,29 @@ +setTitle('Error'); +?> +
+

Error

+ +

+ Go Home +

+
diff --git a/src/Presentation/Site/Widget/CategoriesPanel/CategoriesPanel.php b/src/Presentation/Site/Widget/CategoriesPanel/CategoriesPanel.php new file mode 100644 index 0000000000000..1e06f8555dab1 --- /dev/null +++ b/src/Presentation/Site/Widget/CategoriesPanel/CategoriesPanel.php @@ -0,0 +1,43 @@ + */ + private readonly array $categories, + private readonly ?int $currentCategoryId, + private readonly WebView $view, + ) {} + + /** + * @param list $categories + */ + public static function create(array $categories, ?int $currentCategoryId = null): self + { + return self::widget([$categories, $currentCategoryId]); + } + + + public function render(): string + { + if (empty($this->categories)) { + return ''; + } + + return $this->view->render( + __DIR__ . '/template.php', + [ + 'categories' => $this->categories, + 'currentCategoryId' => $this->currentCategoryId, + ], + ); + } +} diff --git a/src/Presentation/Site/Widget/CategoriesPanel/template.php b/src/Presentation/Site/Widget/CategoriesPanel/template.php new file mode 100644 index 0000000000000..9836196c9c8f2 --- /dev/null +++ b/src/Presentation/Site/Widget/CategoriesPanel/template.php @@ -0,0 +1,33 @@ + $categories + * @var int|null $currentCategoryId + */ +?> +
+ + name) + . ' ' + . Html::span( + (string) $category->countPosts, + ['class' => 'badge bg-light text-dark'], + ), + $urlGenerator->category($category->slug), + [ + 'class' => [ + 'btn btn-light btn-sm d-flex align-items-center gap-2', + $currentCategoryId === $category->id ? 'active' : null, + ], + ], + )->encode(false) ?> + +
diff --git a/src/Presentation/Site/Widget/PostsList/PostsList.php b/src/Presentation/Site/Widget/PostsList/PostsList.php new file mode 100644 index 0000000000000..f3c97c526d71b --- /dev/null +++ b/src/Presentation/Site/Widget/PostsList/PostsList.php @@ -0,0 +1,34 @@ +paginator->read()]; + + return empty($posts) + ? $this->view->render(__DIR__ . '/empty.php') + : $this->view->render( + __DIR__ . '/template.php', + [ + 'posts' => $posts, + 'paginator' => $this->paginator, + ], + ); + } +} diff --git a/src/Presentation/Site/Widget/PostsList/empty.php b/src/Presentation/Site/Widget/PostsList/empty.php new file mode 100644 index 0000000000000..a66f8a288b76a --- /dev/null +++ b/src/Presentation/Site/Widget/PostsList/empty.php @@ -0,0 +1,6 @@ + +

No posts published yet.

diff --git a/src/Presentation/Site/Widget/PostsList/template.php b/src/Presentation/Site/Widget/PostsList/template.php new file mode 100644 index 0000000000000..2502c1f211210 --- /dev/null +++ b/src/Presentation/Site/Widget/PostsList/template.php @@ -0,0 +1,66 @@ + + + +
+
+
+ title, $urlGenerator->post($post->slug), [ + 'class' => 'text-dark text-decoration-underline link-primary link-opacity-100-hover', + ]) ?> +
+
+ + asLongDate($post->publication_date); + ?> + +
+

+ body, 500)) ?> +

+ getCategories(); + if ($categories !== []) { + ?> +
+ + name, + $urlGenerator->category($category->slug), + [ + 'class' => 'badge fw-light bg-light text-dark border text-decoration-none link-primary link-opacity-75-hover', + ], + ) ?> + +
+ +
+
+ +diary(PaginationContext::URL_PLACEHOLDER), + $urlGenerator->diary(), +) ?> diff --git a/src/Presentation/Site/Widget/ShortUserInfo.php b/src/Presentation/Site/Widget/ShortUserInfo.php new file mode 100644 index 0000000000000..4c904f7887ec4 --- /dev/null +++ b/src/Presentation/Site/Widget/ShortUserInfo.php @@ -0,0 +1,41 @@ +user->getId()); + $login = Html::encode($this->user->login); + return << + + + User Information + + + + + ID + $id + + + Login + $login + + + + HTML; + } +} diff --git a/src/Shared/Formatter.php b/src/Shared/Formatter.php new file mode 100644 index 0000000000000..c84a1d209f07c --- /dev/null +++ b/src/Shared/Formatter.php @@ -0,0 +1,29 @@ +formatIntlDateFormatter( + new IntlDateFormatter(null, IntlDateFormatter::LONG, IntlDateFormatter::NONE), + $value, + ); + } + + private function formatIntlDateFormatter(IntlDateFormatter $formatter, DateTimeInterface $value): string + { + $result = $formatter->format($value); + if ($result === false) { + throw new LogicException('Unexpected error on date formatting.'); + } + return $result; + } +} diff --git a/src/Shared/Read/PublicCategoriesWithCountPosts/Category.php b/src/Shared/Read/PublicCategoriesWithCountPosts/Category.php new file mode 100644 index 0000000000000..11feff2d4385a --- /dev/null +++ b/src/Shared/Read/PublicCategoriesWithCountPosts/Category.php @@ -0,0 +1,15 @@ + $rows + */ + $rows = \App\Domain\Category\Category::query() + ->select([ + 'category.id', + 'category.name', + 'category.slug', + 'COUNT(post.id) AS post_count', + ]) + ->joinWith('posts', false) + ->groupBy(['category.id', 'category.name', 'category.slug']) + ->asArray() + ->all(); + + return array_map( + static fn(array $row) => new Category( + (int) $row['id'], + $row['name'], + $row['slug'], + (int) $row['post_count'], + ), + $rows, + ); + } +} diff --git a/src/Shared/UrlGenerator.php b/src/Shared/UrlGenerator.php new file mode 100644 index 0000000000000..e97924c3e1fd5 --- /dev/null +++ b/src/Shared/UrlGenerator.php @@ -0,0 +1,91 @@ +generate('home'); + } + + public function login(): string + { + return $this->generate('login'); + } + + public function logout(): string + { + return $this->generate('logout'); + } + + public function profileChangePassword(): string + { + return $this->generate('profile/change-password'); + } + + public function profileUpdate(): string + { + return $this->generate('profile/update'); + } + + public function diary(int|string $page = 1): string + { + return $this->generate('diary/post/index', $page === 1 ? [] : ['page' => $page]); + } + + public function category(string $slug, int|string $page = 1, bool $absolute = false): string + { + $arguments = [ + 'slug' => $slug, + ...($page === 1 ? [] : ['page' => $page]), + ]; + return $absolute + ? $this->generateAbsolute('diary/category/index', $arguments) + : $this->generate('diary/category/index', $arguments); + } + + public function categoryUpdate(int $id): string + { + return $this->generate('diary/manage/category/update', ['id' => $id]); + } + + public function post(string $slug, bool $absolute = false): string + { + return $absolute + ? $this->generateAbsolute('diary/post/view', ['slug' => $slug]) + : $this->generate('diary/post/view', ['slug' => $slug]); + } + + public function postUpdate(int $id): string + { + return $this->generate('diary/manage/post/update', ['id' => $id]); + } + + /** + * @param UrlArgumentsType $arguments + */ + public function generate(string $name, array $arguments = [], array $queryParameters = []): string + { + return $this->generator->generate($name, $arguments, $queryParameters); + } + + /** + * @param UrlArgumentsType $arguments + */ + public function generateAbsolute(string $name, array $arguments = [], array $queryParameters = []): string + { + return $this->generator->generateAbsolute($name, $arguments, $queryParameters); + } +} diff --git a/src/UseCase/Diary/Api/Category/List/Action.php b/src/UseCase/Diary/Api/Category/List/Action.php new file mode 100644 index 0000000000000..3654dd028bee2 --- /dev/null +++ b/src/UseCase/Diary/Api/Category/List/Action.php @@ -0,0 +1,30 @@ +responseFactory->success( + $this->categoryReader->find(), + new CollectionPresenter( + new CategoryPresenter($this->urlGenerator), + ), + ); + } +} diff --git a/src/UseCase/Diary/Api/Category/List/CategoryPresenter.php b/src/UseCase/Diary/Api/Category/List/CategoryPresenter.php new file mode 100644 index 0000000000000..371cd8913afff --- /dev/null +++ b/src/UseCase/Diary/Api/Category/List/CategoryPresenter.php @@ -0,0 +1,29 @@ + + */ +final readonly class CategoryPresenter implements PresenterInterface +{ + public function __construct( + private UrlGenerator $urlGenerator, + ) {} + + public function present(mixed $value): array + { + return [ + 'id' => $value->id, + 'name' => $value->name, + 'url' => $this->urlGenerator->category($value->slug, absolute: true), + 'count_posts' => $value->countPosts, + ]; + } +} diff --git a/src/UseCase/Diary/Api/Post/List/Action.php b/src/UseCase/Diary/Api/Post/List/Action.php new file mode 100644 index 0000000000000..b721f5112bd56 --- /dev/null +++ b/src/UseCase/Diary/Api/Post/List/Action.php @@ -0,0 +1,47 @@ +categoryId !== null) { + $postQuery + ->joinWith('categories') + ->andWhere(['category.id' => $input->categoryId]); + } + $paginator = new OffsetPaginator( + new QueryDataReader($postQuery), + ); + + if ($input->page !== 1 && $input->page > $paginator->getTotalPages()) { + return $this->responseFactory->fail('Page not found.', httpCode: Status::NOT_FOUND); + } + $paginator = $paginator->withCurrentPage($input->page); + + return $this->responseFactory->success( + $paginator, + new OffsetPaginatorPresenter( + new PostPresenter($this->urlGenerator), + ), + ); + } +} diff --git a/src/UseCase/Diary/Api/Post/List/Input.php b/src/UseCase/Diary/Api/Post/List/Input.php new file mode 100644 index 0000000000000..f0c0fc5cea710 --- /dev/null +++ b/src/UseCase/Diary/Api/Post/List/Input.php @@ -0,0 +1,21 @@ + + */ +final readonly class PostPresenter implements PresenterInterface +{ + public function __construct( + private UrlGenerator $urlGenerator, + ) {} + + public function present(mixed $value): array + { + /** @var DateTimeImmutable $publicationDate */ + $publicationDate = $value->publication_date; + + return [ + 'id' => $value->getId(), + 'title' => $value->title, + 'url' => $this->urlGenerator->post($value->slug, absolute: true), + 'body' => $value->body, + 'publicationDate' => $publicationDate->format('Y-m-d'), + 'categories' => array_map( + static fn($category) => $category->getId(), + $value->getCategories(), + ), + ]; + } +} diff --git a/src/UseCase/Diary/Front/Category/Action.php b/src/UseCase/Diary/Front/Category/Action.php new file mode 100644 index 0000000000000..893a1d2c00ea3 --- /dev/null +++ b/src/UseCase/Diary/Front/Category/Action.php @@ -0,0 +1,64 @@ +where(['slug' => $slug])->one(); + if ($category === null) { + return $this->responseFactory->notFound(); + } + + $paginator = new OffsetPaginator( + new QueryDataReader( + Post::publicQuery() + ->joinWith('categories') + ->andWhere(['category.id' => $category->getId()]), + ), + ); + + if ($page !== 1 + && ($page < 1 || $page > $paginator->getTotalPages()) + ) { + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->category($category->slug), + ); + } + + $paginator = $paginator->withCurrentPage($page); + + return $this->responseFactory->render( + __DIR__ . '/template.php', + [ + 'category' => $category, + 'paginator' => $paginator, + 'categories' => $this->categoryReader->find(), + ], + ); + } +} diff --git a/src/UseCase/Diary/Front/Category/template.php b/src/UseCase/Diary/Front/Category/template.php new file mode 100644 index 0000000000000..88d37fdb5f408 --- /dev/null +++ b/src/UseCase/Diary/Front/Category/template.php @@ -0,0 +1,62 @@ + $categories + */ + +$this->setTitle($category->name . ' / Diary'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb( + $category->name, + urlName: $paginator->isOnFirstPage() ? null : 'diary/category/index', + urlParameters: ['slug' => $category->slug], + ), +); +?> +
+

name) ?>

+ can(Permission::DiaryManage)): ?> +
+ Edit'), + $urlGenerator->categoryUpdate($category->getId()), + ['class' => 'btn btn-outline-primary btn-sm'], + ) ?> +
+ +
+desc !== '') { ?> +
+

+ desc)) ?> +

+
+ +
+ +
+getId()) ?> diff --git a/src/UseCase/Diary/Front/Listing/Action.php b/src/UseCase/Diary/Front/Listing/Action.php new file mode 100644 index 0000000000000..f4c7451b76eab --- /dev/null +++ b/src/UseCase/Diary/Front/Listing/Action.php @@ -0,0 +1,52 @@ + $paginator->getTotalPages()) + ) { + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->diary(), + ); + } + + $paginator = $paginator->withCurrentPage($page); + + return $this->responseFactory->render( + __DIR__ . '/template.php', + [ + 'paginator' => $paginator, + 'categories' => $this->categoriesReader->find(), + ], + ); + } +} diff --git a/src/UseCase/Diary/Front/Listing/template.php b/src/UseCase/Diary/Front/Listing/template.php new file mode 100644 index 0000000000000..5a0ba35b866f0 --- /dev/null +++ b/src/UseCase/Diary/Front/Listing/template.php @@ -0,0 +1,48 @@ + $categories + */ + +$this->setTitle('Diary'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: $paginator->isOnFirstPage() ? null : 'diary/post/index'), +); +?> +
+

Diary

+ can(Permission::DiaryManage)): ?> +
+ Manage'), + $urlGenerator->generate('diary/manage/post/index'), + ['class' => 'btn btn-outline-secondary btn-sm'], + ) ?> +
+ +
+ +
+ +
diff --git a/src/UseCase/Diary/Front/Post/Action.php b/src/UseCase/Diary/Front/Post/Action.php new file mode 100644 index 0000000000000..4d61c724aed34 --- /dev/null +++ b/src/UseCase/Diary/Front/Post/Action.php @@ -0,0 +1,35 @@ +andWhere(['slug' => $slug])->one(); + if ($post === null) { + return $this->responseFactory->notFound(); + } + + return $this->responseFactory->render( + __DIR__ . '/template.php', + [ + 'post' => $post, + ], + ); + } +} diff --git a/src/UseCase/Diary/Front/Post/template.php b/src/UseCase/Diary/Front/Post/template.php new file mode 100644 index 0000000000000..ea9205c59e0a9 --- /dev/null +++ b/src/UseCase/Diary/Front/Post/template.php @@ -0,0 +1,68 @@ +setTitle($post->title); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', $urlGenerator->diary()), + new Breadcrumb($post->title), +); +?> +
+
+
+

title) ?>

+ can(Permission::DiaryManage)): ?> +
+ Edit'), + $urlGenerator->postUpdate($post->getId()), + ['class' => 'btn btn-outline-primary btn-sm'], + ) ?> +
+ +
+
+ + asLongDate($post->publication_date) +?> + +
+ getCategories(); +if ($categories !== []) { + ?> +
+ + name, + $urlGenerator->generate('diary/category/index', ['slug' => $category->slug]), + ['class' => 'badge fw-light bg-light text-dark border text-decoration-none link-primary link-opacity-75-hover me-2'], + ) ?> + +
+ +
+ body)) ?> +
diff --git a/src/UseCase/Diary/Manage/Category/Create/Action.php b/src/UseCase/Diary/Manage/Category/Create/Action.php new file mode 100644 index 0000000000000..cfbc1d381f192 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Create/Action.php @@ -0,0 +1,70 @@ +formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + $slug = $form->slug === '' + ? mb_substr($this->inflector->toSlug($form->name), 0, Category::MAX_SLUG_LENGTH) + : $form->slug; + if (Category::query()->where(['slug' => $slug])->exists()) { + $form->getValidationResult()->addError( + sprintf('Category with slug "%s" already exist.', $slug), + valuePath: ['slug'], + ); + return $this->renderForm($form); + } + + $category = new Category(); + $category->name = $form->name; + $category->desc = $form->description; + $category->slug = $slug; + $category->save(); + + $this->contentNotices->success( + sprintf( + 'Category "%s" with ID "%s" is created.', + $form->name, + $category->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('diary/manage/category/index')); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Category/Create/Form.php b/src/UseCase/Diary/Manage/Category/Create/Form.php new file mode 100644 index 0000000000000..29df669b86262 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Create/Form.php @@ -0,0 +1,28 @@ +setTitle('New category'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Categories', urlName: 'diary/manage/category/index'), + new Breadcrumb('New category'), +); + +$field = new FieldFactory(); +?> +

Create Category

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->generate('diary/manage/category/create')) + ->csrf($csrf) + ->open() ?> + text($form, 'name') ?> + textarea($form, 'description')->addInputAttributes(['rows' => 3]) ?> + text($form, 'slug') ?> + submitButton('Create')->afterInput( + Html::a('Cancel', $urlGenerator->generate('diary/manage/category/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/Diary/Manage/Category/Delete/Action.php b/src/UseCase/Diary/Manage/Category/Delete/Action.php new file mode 100644 index 0000000000000..0792ea319d4fc --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Delete/Action.php @@ -0,0 +1,54 @@ +findByPk($categoryId) ?? throw new UserException('Category not found.'); + + if ($request->getMethod() !== Method::POST) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['category' => $category], + ); + } + + $category->unlinkAll('posts', true); + $category->delete(); + + $this->contentNotices->success( + sprintf( + 'Category "%s" with ID "%s" is deleted.', + $category->name, + $category->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('diary/manage/category/index')); + } +} diff --git a/src/UseCase/Diary/Manage/Category/Delete/template.php b/src/UseCase/Diary/Manage/Category/Delete/template.php new file mode 100644 index 0000000000000..c2f79c7760d25 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Delete/template.php @@ -0,0 +1,46 @@ +setTitle('Delete category "' . $category->name . '"'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Categories', urlName: 'diary/manage/category/index'), + new Breadcrumb('Delete category'), +); +?> +

Delete category "name) ?>"?

+
+
+ ID: getId()) ?>
+ Slug: slug) ?> +
+
+ Warning: Deleting this category will remove it from all posts that use it. +
+
+ post($urlGenerator->generate('diary/manage/category/delete', ['id' => $category->getId()])) + ->csrf($csrf) + ->open() ?> + 'btn btn-danger']) ?> + generate('diary/manage/category/index'), ['class' => 'btn btn-outline-secondary']) ?> + ' ?> +
+
diff --git a/src/UseCase/Diary/Manage/Category/Listing/Action.php b/src/UseCase/Diary/Manage/Category/Listing/Action.php new file mode 100644 index 0000000000000..5099bd716aad9 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Listing/Action.php @@ -0,0 +1,27 @@ +responseFactory->render( + __DIR__ . '/template.php', + [ + 'dataReader' => $this->dataReader, + ], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Category/Listing/DataReader/Category.php b/src/UseCase/Diary/Manage/Category/Listing/DataReader/Category.php new file mode 100644 index 0000000000000..835d5d681b9b3 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Listing/DataReader/Category.php @@ -0,0 +1,16 @@ + + */ +final class CategoryDataReader extends QueryDataReader +{ + public function __construct(ConnectionInterface $db) + { + parent::__construct( + $db->createQuery() + ->select([ + 'c.id', + 'c.name', + 'c.desc', + 'c.slug', + 'COUNT(pc.post_id) AS count_posts', + ]) + ->from('category c') + ->leftJoin('post_category pc', 'c.id = pc.category_id') + ->groupBy('c.id') + ->resultCallback( + static function (array $rows): array { + /** + * @var non-empty-list $rows + */ + return array_map( + static fn(array $row) => new Category( + id: (int) $row['id'], + name: $row['name'], + description: $row['desc'], + slug: $row['slug'], + countPosts: (int) $row['count_posts'], + ), + $rows, + ); + }, + ), + Sort::only(['name', 'countPosts'])->withOrder(['name' => 'asc']), + fieldMapper: [ + 'id' => 'c.id', + 'name' => 'c.name', + 'description' => 'c.desc', + 'slug' => 'c.slug', + 'countPosts' => 'count_posts', + ], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Category/Listing/NameFilterFactory.php b/src/UseCase/Diary/Manage/Category/Listing/NameFilterFactory.php new file mode 100644 index 0000000000000..e2ff3b8076fd2 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Listing/NameFilterFactory.php @@ -0,0 +1,21 @@ +setTitle('Categories'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Categories'), +); +?> +
+

Categories

+ Create category'), + $urlGenerator->generate('diary/manage/category/create'), + ['class' => 'btn btn-outline-primary btn-sm'], + ) ?> +
+dataReader($dataReader) + ->containerClass('mt-4') + ->columns( + new DataColumn( + 'name', + header: 'Category', + content: static function (Category $category): string { + return Html::encode($category->name) + . '
' + . Html::small((string) $category->id, ['class' => 'text-muted']); + }, + encodeContent: false, + filter: true, + filterFactory: new NameFilterFactory(), + ), + new DataColumn( + 'countPosts', + header: 'Count Posts', + ), + new ActionColumn( + before: '
', + after: '
', + buttons: [ + new ActionButton( + Html::i()->class('bi bi-eye'), + static fn(Category $category) => $urlGenerator->category($category->slug), + title: 'View', + ), + new ActionButton( + Html::i()->class('bi bi-pencil'), + static fn(Category $category) => $urlGenerator->categoryUpdate($category->id), + title: 'Edit', + ), + new ActionButton( + Html::i()->class('bi bi-x-lg'), + static fn(Category $category) => $urlGenerator->generate('diary/manage/category/delete', ['id' => $category->id]), + title: 'Delete', + ), + ], + ), + ) ?> diff --git a/src/UseCase/Diary/Manage/Category/Update/Action.php b/src/UseCase/Diary/Manage/Category/Update/Action.php new file mode 100644 index 0000000000000..c53a9299aec58 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Update/Action.php @@ -0,0 +1,77 @@ +findByPk($categoryId) ?? throw new UserException('Category not found.'); + + $form = new Form($category); + + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + $slug = $form->slug; + if ($slug === '') { + $slug = mb_substr($this->inflector->toSlug($form->name), 0, Category::MAX_SLUG_LENGTH); + } + if (Category::query()->where(['slug' => $slug])->andWhere(['!=', 'id', $category->getId()])->exists()) { + $form->getValidationResult()->addError( + sprintf('Category with slug "%s" already exist.', $slug), + valuePath: ['slug'], + ); + return $this->renderForm($form); + } + + $category->name = $form->name; + $category->desc = $form->description; + $category->slug = $slug; + $category->save(); + + $this->contentNotices->success( + sprintf( + 'Category "%s" is updated.', + $form->name, + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('diary/manage/category/index')); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Category/Update/Form.php b/src/UseCase/Diary/Manage/Category/Update/Form.php new file mode 100644 index 0000000000000..3ca6ee9d2dc29 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Update/Form.php @@ -0,0 +1,36 @@ +name = $this->category->name; + $this->description = $this->category->desc; + $this->slug = $this->category->slug; + } +} diff --git a/src/UseCase/Diary/Manage/Category/Update/template.php b/src/UseCase/Diary/Manage/Category/Update/template.php new file mode 100644 index 0000000000000..9258cdc2133d8 --- /dev/null +++ b/src/UseCase/Diary/Manage/Category/Update/template.php @@ -0,0 +1,47 @@ +setTitle('Update category'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Categories', urlName: 'diary/manage/category/index'), + new Breadcrumb('Update category'), +); + +$field = new FieldFactory(); +?> +

Update Category

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->categoryUpdate($form->category->getId())) + ->csrf($csrf) + ->open() ?> + text($form, 'name') ?> + textarea($form, 'description')->addInputAttributes(['rows' => 3]) ?> + text($form, 'slug') ?> + submitButton('Save')->afterInput( + Html::a('Cancel', $urlGenerator->generate('diary/manage/category/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/Diary/Manage/Post/Create/Action.php b/src/UseCase/Diary/Manage/Post/Create/Action.php new file mode 100644 index 0000000000000..a8b345024e7ac --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Create/Action.php @@ -0,0 +1,86 @@ + $categories */ + $categories = Category::query()->select('name')->indexBy('id')->column(); + $form = new Form($categories); + + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + $slug = $form->slug === '' + ? mb_substr($this->inflector->toSlug($form->title), 0, Post::MAX_SLUG_LENGTH) + : $form->slug; + if (Post::query()->where(['slug' => $slug])->exists()) { + $form->getValidationResult()->addError( + sprintf('Post with slug "%s" already exist.', $slug), + valuePath: ['slug'], + ); + return $this->renderForm($form); + } + + $currentUserId = $this->authenticatedUserProvider->getId(); + + $post = new Post(); + $post->title = $form->title; + $post->body = $form->body; + $post->slug = $slug; + $post->status = $form->status; + $post->publication_date = $form->publicationDate; + $post->created_by = $post->updated_by = $currentUserId; + $post->created_at = $post->updated_at = new DateTimeImmutable(); + $post->save(); + foreach (Category::query()->where(['id' => $form->categoryIds])->all() as $category) { + /** @var Category $category */ + $post->link('categories', $category); + } + + $this->contentNotices->success( + sprintf( + 'Post "%s" with ID "%s" is created.', + $form->title, + $post->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('diary/manage/post/index')); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Create/Form.php b/src/UseCase/Diary/Manage/Post/Create/Form.php new file mode 100644 index 0000000000000..ccc7e6301ef1e --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Create/Form.php @@ -0,0 +1,68 @@ + + */ + #[Label('Categories')] + #[ToArrayOfStrings] + #[Safe] + public array $categoryIds = []; + + public function __construct( + /** @var array */ + public readonly array $categories, + ) {} + + public function validatePublicationDate(mixed $value): Result + { + if ($this->status === PostStatus::Published && $value === null) { + return new Result()->addError( + sprintf('Publication date is required when status is "%s".', PostStatus::Published->label()), + ); + } + return new Result(); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Create/template.php b/src/UseCase/Diary/Manage/Post/Create/template.php new file mode 100644 index 0000000000000..e8142b8686ba6 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Create/template.php @@ -0,0 +1,50 @@ +setTitle('New post'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('New post'), +); + +$field = new FieldFactory(); +?> +

Create Post

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->generate('diary/manage/post/create')) + ->csrf($csrf) + ->open() ?> + text($form, 'title') ?> + textarea($form, 'body')->addInputAttributes(['rows' => 10]) ?> + checkboxList($form, 'categoryIds')->items($form->categories)->uncheckValue('') ?> + text($form, 'slug') ?> + select($form, 'status')->optionsData(PostStatus::labelsByValue()) ?> + date($form, 'publicationDate') ?> + submitButton('Create')->afterInput( + Html::a('Cancel', $urlGenerator->generate('diary/manage/post/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/Diary/Manage/Post/Delete/Action.php b/src/UseCase/Diary/Manage/Post/Delete/Action.php new file mode 100644 index 0000000000000..23b9a5d17f1f3 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Delete/Action.php @@ -0,0 +1,54 @@ +findByPk($postId) ?? throw new UserException('Post not found.'); + + if ($request->getMethod() !== Method::POST) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['post' => $post], + ); + } + + $post->unlinkAll('categories', true); + $post->delete(); + + $this->contentNotices->success( + sprintf( + 'Post "%s" with ID "%s" is deleted.', + $post->title, + $post->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('diary/manage/post/index')); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Delete/template.php b/src/UseCase/Diary/Manage/Post/Delete/template.php new file mode 100644 index 0000000000000..6b8a9b5db94f6 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Delete/template.php @@ -0,0 +1,42 @@ +setTitle('Delete post "' . $post->title . '"'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Delete post'), +); +?> +

Delete post "title) ?>"?

+
+
+ body, 500)) ?> +
+
+ post($urlGenerator->generate('diary/manage/post/delete', ['id' => $post->getId()])) + ->csrf($csrf) + ->open() ?> + 'btn btn-danger']) ?> + generate('diary/manage/post/index'), ['class' => 'btn btn-outline-secondary']) ?> + ' ?> +
+
diff --git a/src/UseCase/Diary/Manage/Post/Listing/Action.php b/src/UseCase/Diary/Manage/Post/Listing/Action.php new file mode 100644 index 0000000000000..cf6e4be119cd6 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Listing/Action.php @@ -0,0 +1,31 @@ +responseFactory->render( + __DIR__ . '/template.php', + [ + 'dataReader' => $dataReader, + ], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Listing/PostStatusBadge.php b/src/UseCase/Diary/Manage/Post/Listing/PostStatusBadge.php new file mode 100644 index 0000000000000..8ae1bd3d65458 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Listing/PostStatusBadge.php @@ -0,0 +1,26 @@ +status) { + PostStatus::Draft, + PostStatus::Archived => 'bg-secondary', + PostStatus::Published => 'bg-success', + }; + return Html::span($this->status->label(), ['class' => ['badge', $badgeClass]])->render(); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Listing/TitleFilterFactory.php b/src/UseCase/Diary/Manage/Post/Listing/TitleFilterFactory.php new file mode 100644 index 0000000000000..36d816665a92b --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Listing/TitleFilterFactory.php @@ -0,0 +1,21 @@ + $dataReader + */ + +$this->setTitle('Posts'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage'), +); +?> +
+

Posts

+
+ Categories'), + $urlGenerator->generate('diary/manage/category/index'), + ['class' => 'btn btn-outline-secondary btn-sm me-1'], + ) ?> + Create post'), + $urlGenerator->generate('diary/manage/post/create'), + ['class' => 'btn btn-outline-primary btn-sm'], + ) ?> +
+
+dataReader($dataReader) + ->containerClass('mt-4') + ->columns( + new DataColumn( + 'title', + header: 'Post', + content: static function (Post $post): string { + return Html::encode($post->title) + . '
' + . Html::small((string) $post->getId(), ['class' => 'text-muted']); + }, + encodeContent: false, + filter: true, + filterFactory: new TitleFilterFactory(), + ), + new DataColumn( + 'status', + content: static fn(Post $post) => PostStatusBadge::widget([$post->status]), + filter: PostStatus::labelsByValue(), + ), + new DataColumn( + 'publicationDate', + header: 'Publication Date', + content: static function (Post $post): string { + return $post->publication_date?->format('Y-m-d') ?? 'not set'; + }, + encodeContent: false, + ), + new DataColumn( + 'categories', + content: static function (Post $post): string { + $names = array_map( + static fn($category) => Html::encode($category->name), + $post->getCategories(), + ); + return implode(', ', $names); + }, + ), + new DataColumn( + header: 'Info', + content: static function (Post $post): string { + return Html::encode($post->getCreatedByUser()->name) + . ' ' + . Html::small($post->created_at->format('Y-m-d H:i:s'), ['class' => 'text-muted']) + . '
' + . Html::encode($post->getUpdatedByUser()->name) + . ' ' + . Html::small($post->updated_at->format('Y-m-d H:i:s'), ['class' => 'text-muted']); + }, + encodeContent: false, + ), + new ActionColumn( + before: '
', + after: '
', + buttons: [ + new ActionButton( + Html::i()->class('bi bi-eye'), + static fn(Post $post) => $urlGenerator->post($post->slug), + title: 'View', + ), + new ActionButton( + Html::i()->class('bi bi-pencil'), + static fn(Post $post) => $urlGenerator->postUpdate($post->getId()), + title: 'Update', + ), + new ActionButton( + Html::i()->class('bi bi-x-lg'), + static fn(Post $post) => $urlGenerator->generate('diary/manage/post/delete', ['id' => $post->getId()]), + title: 'Delete', + ), + ], + ), + ) +?> diff --git a/src/UseCase/Diary/Manage/Post/Update/Action.php b/src/UseCase/Diary/Manage/Post/Update/Action.php new file mode 100644 index 0000000000000..29ed266811505 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Update/Action.php @@ -0,0 +1,96 @@ +findByPk($postId) ?? throw new UserException('Post not found.'); + + /** @var array $categories */ + $categories = Category::query()->select('name')->indexBy('id')->column(); + $form = new Form($post, $categories); + + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + $slug = $form->slug === '' + ? mb_substr($this->inflector->toSlug($form->title), 0, Post::MAX_SLUG_LENGTH) + : $form->slug; + if (Post::query()->where(['slug' => $slug])->andWhere(['!=', 'id', $post->getId()])->exists()) { + $form->getValidationResult()->addError( + sprintf('Post with slug "%s" already exist.', $slug), + valuePath: ['slug'], + ); + return $this->renderForm($form); + } + + $post->title = $form->title; + $post->body = $form->body; + $post->slug = $slug; + $post->status = $form->status; + $post->publication_date = $form->publicationDate; + $post->updated_at = new DateTimeImmutable(); + $post->updated_by = $this->authenticatedUserProvider->getId(); + $post->save(); + $post->unlinkAll('categories', true); + foreach (Category::query()->where(['id' => $form->categoryIds])->all() as $category) { + /** @var Category $category */ + $post->link( + 'categories', + $category, + ); + } + + $this->contentNotices->success( + sprintf( + 'Post "%s" is updated.', + $form->title, + ), + ); + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->postUpdate($post->getId()), + ); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Update/Form.php b/src/UseCase/Diary/Manage/Post/Update/Form.php new file mode 100644 index 0000000000000..a40b2d8238558 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Update/Form.php @@ -0,0 +1,77 @@ + + */ + #[Label('Categories')] + #[ToArrayOfStrings] + #[Safe] + public array $categoryIds; + + public function __construct( + public readonly Post $post, + /** @var array */ + public readonly array $categories, + ) { + $this->title = $this->post->title; + $this->body = $this->post->body; + $this->slug = $this->post->slug; + $this->status = $this->post->status; + $this->publicationDate = $this->post->publication_date; + /** @var list */ + $this->categoryIds = $this->post->relationQuery('categories')->select('id')->column(); + } + + public function validatePublicationDate(mixed $value): Result + { + if ($this->status === PostStatus::Published && $value === null) { + return new Result()->addError( + sprintf('Publication date is required when status is "%s".', PostStatus::Published->label()), + ); + } + return new Result(); + } +} diff --git a/src/UseCase/Diary/Manage/Post/Update/template.php b/src/UseCase/Diary/Manage/Post/Update/template.php new file mode 100644 index 0000000000000..1b51fd1716225 --- /dev/null +++ b/src/UseCase/Diary/Manage/Post/Update/template.php @@ -0,0 +1,50 @@ +setTitle('Update post'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Diary', urlName: 'diary/post/index'), + new Breadcrumb('Manage', urlName: 'diary/manage/post/index'), + new Breadcrumb('Update post'), +); + +$field = new FieldFactory(); +?> +

Update Post

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->postUpdate($form->post->getId())) + ->csrf($csrf) + ->open() ?> + text($form, 'title') ?> + textarea($form, 'body')->addInputAttributes(['rows' => 10]) ?> + checkboxList($form, 'categoryIds')->items($form->categories)->uncheckValue('') ?> + text($form, 'slug') ?> + select($form, 'status')->optionsData(PostStatus::labelsByValue()) ?> + date($form, 'publicationDate') ?> + submitButton('Save')->afterInput( + Html::a('Cancel', $urlGenerator->generate('diary/manage/post/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/FakeData/FakeDataCommand.php b/src/UseCase/FakeData/FakeDataCommand.php new file mode 100644 index 0000000000000..b5d5eda066d7b --- /dev/null +++ b/src/UseCase/FakeData/FakeDataCommand.php @@ -0,0 +1,188 @@ +faker = Factory::create(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $io->info('Clearing existing data...'); + $this->clearData(); + + $io->info('Creating admin user...'); + $adminUser = $this->createAdministrator(); + + $io->info('Creating ' . self::USERS_COUNT . ' fake users...'); + $users = $this->createFakeUsers(); + $users[] = $adminUser; + + $io->info('Creating ' . self::CATEGORIES_COUNT . ' fake categories...'); + $categories = $this->createFakeCategories(); + + $io->info('Creating ' . self::POSTS_COUNT . ' fake posts...'); + $this->createFakePosts($users, $categories); + + $io->success('Fake data has been created successfully!'); + $io->table(['Type', 'Count'], [ + ['Administrator', '1 (login: ' . self::ADMIN_LOGIN . ', password: ' . self::ADMIN_PASSWORD . ')'], + ['Editors', (string) self::USERS_COUNT], + ['Categories', (string) self::CATEGORIES_COUNT], + ['Posts', (string) self::POSTS_COUNT], + ]); + + return ExitCode::OK; + } + + private function clearData(): void + { + $this->db->createCommand()->delete('post_category')->execute(); + $this->db->createCommand()->delete('post')->execute(); + $this->db->createCommand()->delete('category')->execute(); + $this->db->createCommand()->delete('user')->execute(); + } + + private function createAdministrator(): User + { + $user = new User(); + $user->login = 'admin'; + $user->name = 'Administrator'; + $user->password_hash = $this->passwordHasher->hash('q1w2e3r4'); + $user->auth_key = $this->authKeyGenerator->generate(); + + $user->save(); + $this->rbacManager->assign(Role::Admin->value, $user->getId()); + + return $user; + } + + /** + * @return list + */ + private function createFakeUsers(): array + { + $users = []; + for ($i = 0; $i < self::USERS_COUNT; $i++) { + $user = new User(); + $user->login = $this->faker->unique()->userName; + $user->name = $this->faker->name; + $user->password_hash = $this->passwordHasher->hash($this->faker->password(8, 12)); + $user->auth_key = $this->authKeyGenerator->generate(); + $user->save(); + $users[] = $user; + } + + return $users; + } + + /** + * @return list + */ + private function createFakeCategories(): array + { + $categories = []; + for ($i = 0; $i < self::CATEGORIES_COUNT; $i++) { + /** @var string $name */ + $name = $this->faker->unique()->words(2, true); + + $category = new Category(); + $category->name = $name; + $category->slug = $this->createSlug($name); + $category->desc = $this->faker->sentence(10); + $category->save(); + $categories[] = $category; + } + + return $categories; + } + + /** + * @param list $users + * @param list $categories + */ + private function createFakePosts(array $users, array $categories): void + { + for ($i = 0; $i < self::POSTS_COUNT; $i++) { + /** @var list $selectedCategories */ + $selectedCategories = $this->faker->randomElements( + $categories, + $this->faker->numberBetween(1, 3), + ); + + /** @var string $body */ + $body = $this->faker->paragraphs(5, true); + + $post = new Post(); + $post->title = $this->faker->sentence(6, false); + $post->body = $body; + $post->slug = $this->createSlug($post->title); + $post->publication_date = $this->faker->boolean(80) ? new DateTimeImmutable() : null; + $post->created_by = $post->updated_by = $users[array_rand($users)]->getId(); + $post->created_at = $post->updated_at = new DateTimeImmutable(); + $post->status = $post->publication_date === null ? PostStatus::Draft : PostStatus::Published; + $post->save(); + foreach ($selectedCategories as $category) { + $post->link('categories', $category); + } + } + } + + /** + * @return non-empty-string + */ + private function createSlug(string $text): string + { + /** @var non-empty-string */ + return strtolower( + substr( + trim((string) preg_replace('/[^A-Za-z0-9-]+/', '-', $text), '-'), + 0, + 50, + ), + ); + } +} diff --git a/src/UseCase/Home/Action.php b/src/UseCase/Home/Action.php new file mode 100644 index 0000000000000..e59fc8885ffb5 --- /dev/null +++ b/src/UseCase/Home/Action.php @@ -0,0 +1,20 @@ +viewRenderer->render(__DIR__ . '/template'); + } +} diff --git a/src/UseCase/Home/template.php b/src/UseCase/Home/template.php new file mode 100644 index 0000000000000..48229a2e9dced --- /dev/null +++ b/src/UseCase/Home/template.php @@ -0,0 +1,90 @@ +setTitle('Welcome to Yii3 Demo Diary'); +?> + +
+
+

Welcome to Yii3 Demo Diary

+

+ Explore modern web development with Yii3 Framework — + featuring clean architecture, dependency injection, and powerful components. +

+
+

Get Started

+

Ready to explore? Check out these resources:

+ +
+
+

Quick Start

+ +
+
+
+

Create only admin account:

+ ./yii user:create-admin admin q1w2e3r4 +

Or fill the database with fake data:

+ ./yii fake-data +
+
+
+
+

Create only admin account (admin / q1w2e3r4):

+ make create-admin +

Or fill the database with fake data:

+ make fake-data +
+
+
+
+ +
+
diff --git a/src/UseCase/Login/Action.php b/src/UseCase/Login/Action.php new file mode 100644 index 0000000000000..6ea3c2c0b2769 --- /dev/null +++ b/src/UseCase/Login/Action.php @@ -0,0 +1,77 @@ +currentUser->isGuest()) { + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->home()); + } + + $form = new Form(); + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + /** @var User|null $user */ + $user = User::query()->where(['login' => $form->login])->one(); + if ($user === null + || !$user->canSignIn() + || !$this->passwordHasher->validate($form->password, $user->password_hash) + ) { + $form->addError(Form::ERROR_MESSAGE); + return $this->renderForm($form); + } + + $user->auth_key = $this->authKeyGenerator->generate(); + $user->save(); + + $identity = new UserIdentity($user, $this->authKeyGenerator); + if (!$this->currentUser->login($identity)) { + $form->addError('Sign in is failed.'); + return $this->renderForm($form); + } + + $response = $this->responseFactory->createResponse(); + if ($form->rememberMe) { + $response = $this->cookieLogin->addCookie($identity, $response); + } + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->home(), $response); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + Layout::PURE, + ); + } +} diff --git a/src/UseCase/Login/Form.php b/src/UseCase/Login/Form.php new file mode 100644 index 0000000000000..4e26805b38170 --- /dev/null +++ b/src/UseCase/Login/Form.php @@ -0,0 +1,46 @@ +login) > User::MAX_LOGIN_LENGTH + || mb_strlen($this->password) < User::MIN_PASSWORD_LENGTH + || mb_strlen($this->password) > User::MAX_PASSWORD_LENGTH + ) { + $result->addError(self::ERROR_MESSAGE); + } + return $result; + } + + public function getFormName(): string + { + return ''; + } +} diff --git a/src/UseCase/Login/template.php b/src/UseCase/Login/template.php new file mode 100644 index 0000000000000..cad001e6495a0 --- /dev/null +++ b/src/UseCase/Login/template.php @@ -0,0 +1,79 @@ +setTitle('Login'); +$this->addToParameter('htmlClass', 'h-100'); +$this->addToParameter('bodyClass', 'd-flex h-100 align-items-center py-4 bg-body-tertiary'); +?> +
+ + post($urlGenerator->login()) + ->csrf($csrf) + ->open() ?> +
+ login)->addAttributes([ + 'id' => 'LoginFormInputLogin', + 'class' => 'form-control loginForm_login', + 'placeholder' => '', + 'required' => true, + ]) ?> + +
+
+ addAttributes([ + 'id' => 'LoginFormInputPassword', + 'class' => 'form-control loginForm_password', + 'placeholder' => '', + 'required' => true, + ]) ?> + +
+
+ class('form-check-input') + ->id('LoginFormCheckboxRememberMe') + ->checked($form->rememberMe) ?> + +
+ + isValidated() && !$form->isValid()) { + echo Html::div( + implode( + '
', + array_map( + Html::encode(...), + $form->getValidationResult()->getErrorMessages(), + ), + ), + ['class' => 'text-bg-danger p-3 mt-4'], + )->encode(false); + } +?> + ' ?> +
diff --git a/src/UseCase/Logout/Action.php b/src/UseCase/Logout/Action.php new file mode 100644 index 0000000000000..1b2c8302e4e8c --- /dev/null +++ b/src/UseCase/Logout/Action.php @@ -0,0 +1,22 @@ +logout(); + return $responseFactory->temporarilyRedirect($urlGenerator->home()); + } +} diff --git a/src/UseCase/Profile/ChangePassword/Action.php b/src/UseCase/Profile/ChangePassword/Action.php new file mode 100644 index 0000000000000..7653d184f75d6 --- /dev/null +++ b/src/UseCase/Profile/ChangePassword/Action.php @@ -0,0 +1,51 @@ +findByPk( + $this->authenticatedUserProvider->getId(), + ); + + $form = new Form($user, $this->passwordHasher); + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } + + $user->password_hash = $this->passwordHasher->hash($form->new); + $user->save(); + + $this->contentNotices->success('Password changed successfully.'); + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->profileChangePassword(), + ); + } +} diff --git a/src/UseCase/Profile/ChangePassword/Form.php b/src/UseCase/Profile/ChangePassword/Form.php new file mode 100644 index 0000000000000..b1792629c45f7 --- /dev/null +++ b/src/UseCase/Profile/ChangePassword/Form.php @@ -0,0 +1,59 @@ +passwordHasher->validate($value, $this->user->password_hash)) { + return new Result(); + } + return new Result()->addError('Invalid current password.'); + } +} diff --git a/src/UseCase/Profile/ChangePassword/template.php b/src/UseCase/Profile/ChangePassword/template.php new file mode 100644 index 0000000000000..11155087904f8 --- /dev/null +++ b/src/UseCase/Profile/ChangePassword/template.php @@ -0,0 +1,43 @@ +setTitle('Profile / Change password'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Profile'), + new Breadcrumb('Change password'), +); + +$field = new FieldFactory(); +?> +

Change password

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->profileChangePassword()) + ->csrf($csrf) + ->open() ?> + password($form, 'current') ?> + password($form, 'new') ?> + password($form, 'new2') ?> + submitButton('Save') ?> + ' ?> +
+
diff --git a/src/UseCase/Profile/UpdateProfile/Action.php b/src/UseCase/Profile/UpdateProfile/Action.php new file mode 100644 index 0000000000000..d869584944134 --- /dev/null +++ b/src/UseCase/Profile/UpdateProfile/Action.php @@ -0,0 +1,49 @@ +findByPk( + $this->authenticatedUserProvider->getId(), + ); + + $form = new Form($user); + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } + + $user->name = $form->name; + $user->save(); + + $this->contentNotices->success('Profile updated successfully.'); + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->profileUpdate(), + ); + } +} diff --git a/src/UseCase/Profile/UpdateProfile/Form.php b/src/UseCase/Profile/UpdateProfile/Form.php new file mode 100644 index 0000000000000..a0180aa8cd474 --- /dev/null +++ b/src/UseCase/Profile/UpdateProfile/Form.php @@ -0,0 +1,22 @@ +name = $user->name; + } +} diff --git a/src/UseCase/Profile/UpdateProfile/template.php b/src/UseCase/Profile/UpdateProfile/template.php new file mode 100644 index 0000000000000..75ad79031f28f --- /dev/null +++ b/src/UseCase/Profile/UpdateProfile/template.php @@ -0,0 +1,41 @@ +setTitle('Profile / Update profile'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Profile'), + new Breadcrumb('Update'), +); + +$field = new FieldFactory(); +?> +

Update profile

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->profileUpdate()) + ->csrf($csrf) + ->open() ?> + text($form, 'name') ?> + submitButton('Save') ?> + ' ?> +
+
diff --git a/src/UseCase/Users/ChangePassword/Action.php b/src/UseCase/Users/ChangePassword/Action.php new file mode 100644 index 0000000000000..a24ae90e5c9c5 --- /dev/null +++ b/src/UseCase/Users/ChangePassword/Action.php @@ -0,0 +1,54 @@ +findByPk($userId) ?? throw new UserException('User not found.'); + + $form = new Form($user); + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } + + $user->password_hash = $this->passwordHasher->hash($form->password); + $user->save(); + + $this->contentNotices->success(sprintf('Password for user "%s" changed successfully.', $user->login)); + return $this->responseFactory->temporarilyRedirect( + $this->urlGenerator->generate('user/index'), + ); + } +} diff --git a/src/UseCase/Users/ChangePassword/Form.php b/src/UseCase/Users/ChangePassword/Form.php new file mode 100644 index 0000000000000..9936b57aa082c --- /dev/null +++ b/src/UseCase/Users/ChangePassword/Form.php @@ -0,0 +1,27 @@ +setTitle('Change User Password'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Users', $urlGenerator->generate('user/index')), + new Breadcrumb('Change password'), +); + +$field = new FieldFactory(); +?> +

Change User Password

+
+
+ user]) ?> + errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->generate('user/change-password', ['id' => $form->user->getId()])) + ->csrf($csrf) + ->open() ?> + password($form, 'password') ?> + submitButton('Save')->afterInput( + Html::a('Cancel', $urlGenerator->generate('user/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/Users/Create/Action.php b/src/UseCase/Users/Create/Action.php new file mode 100644 index 0000000000000..a621a92460893 --- /dev/null +++ b/src/UseCase/Users/Create/Action.php @@ -0,0 +1,80 @@ +formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + if (User::query()->where(['login' => $form->login])->exists()) { + $form->getValidationResult()->addError('User with this login already exists.', valuePath: ['login']); + return $this->renderForm($form); + } + + /** @var Role $role */ + $role = $form->role; + + $user = new User(); + $user->login = $form->login; + $user->name = $form->name; + $user->password_hash = $this->passwordHasher->hash($form->password); + $user->auth_key = $this->authKeyGenerator->generate(); + $this->db->transaction( + function () use ($user, $role) { + $user->save(); + $this->rbacManager->assign($role->value, $user->getId()); + }, + ); + + $this->contentNotices->success( + sprintf( + 'User "%s" with ID "%s" is created.', + $form->login, + $user->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('user/index')); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Users/Create/Form.php b/src/UseCase/Users/Create/Form.php new file mode 100644 index 0000000000000..bfa9f98202ca4 --- /dev/null +++ b/src/UseCase/Users/Create/Form.php @@ -0,0 +1,29 @@ +setTitle('New user'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Users', $urlGenerator->generate('user/index')), + new Breadcrumb('New user'), +); + +$field = new FieldFactory(); +?> +

New User

+
+
+ errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->generate('user/create')) + ->csrf($csrf) + ->open() ?> + text($form, 'login') ?> + text($form, 'name') ?> + password($form, 'password') ?> + select($form, 'role')->optionsData(Role::labelsByValue())->prompt('— Select —') ?> + submitButton('Create')->afterInput( + Html::a('Cancel', $urlGenerator->generate('user/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/UseCase/Users/CreateAdmin/CreateAdminCommand.php b/src/UseCase/Users/CreateAdmin/CreateAdminCommand.php new file mode 100644 index 0000000000000..88ddd2e531da3 --- /dev/null +++ b/src/UseCase/Users/CreateAdmin/CreateAdminCommand.php @@ -0,0 +1,81 @@ +addArgument('login', InputArgument::REQUIRED) + ->addArgument('password', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $model = new Model($input); + + $errors = $this->validator->validate($model)->getErrorMessages(); + if (!empty($errors)) { + foreach ($errors as $message) { + $io->error($message); + } + return ExitCode::DATAERR; + } + + if (User::query()->where(['login' => $model->login])->exists()) { + $io->error('Login "' . $model->login . '" already exists.'); + return ExitCode::DATAERR; + } + + $user = new User(); + $user->name = $model->login; + $user->login = $model->login; + $user->password_hash = $this->passwordHasher->hash($model->password); + $user->auth_key = $this->authKeyGenerator->generate(); + + $this->db->transaction( + function () use ($user) { + $user->save(); + $this->rbacManager->assign(Role::Admin->value, $user->getId()); + }, + ); + $user->save(); + + $io->success('Created user "' . $user->getId() . '".'); + return ExitCode::OK; + } +} diff --git a/src/UseCase/Users/CreateAdmin/Model.php b/src/UseCase/Users/CreateAdmin/Model.php new file mode 100644 index 0000000000000..aee417a67cb5f --- /dev/null +++ b/src/UseCase/Users/CreateAdmin/Model.php @@ -0,0 +1,27 @@ +login = $input->getArgument('login'); + $this->password = $input->getArgument('password'); + } +} diff --git a/src/UseCase/Users/Delete/Action.php b/src/UseCase/Users/Delete/Action.php new file mode 100644 index 0000000000000..382e0a0327c1d --- /dev/null +++ b/src/UseCase/Users/Delete/Action.php @@ -0,0 +1,62 @@ +findByPk($userId) ?? throw new UserException('User not found.'); + + if ($this->authenticatedUserProvider->getId() === $user->getId()) { + throw new UserException('Cannot delete current user.'); + } + + if ($request->getMethod() !== Method::POST) { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['user' => $user], + ); + } + + if ($user->relationQuery('postsCreatedBy')->exists() || $user->relationQuery('postsUpdatedBy')->exists()) { + throw new UserException('Cannot delete user with existing posts.'); + } + $user->delete(); + + $this->contentNotices->success( + sprintf( + 'User "%s" with ID "%s" is deleted.', + $user->login, + $user->getId(), + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('user/index')); + } +} diff --git a/src/UseCase/Users/Delete/template.php b/src/UseCase/Users/Delete/template.php new file mode 100644 index 0000000000000..8196ab36023ba --- /dev/null +++ b/src/UseCase/Users/Delete/template.php @@ -0,0 +1,36 @@ +setTitle('Delete user "' . $user->login . '"'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Users', $urlGenerator->generate('user/index')), + new Breadcrumb('Delete user'), +); +?> +

Delete user "login) ?>"?

+
+ + post($urlGenerator->generate('user/delete', ['id' => $user->getId()])) + ->csrf($csrf) + ->open() ?> + 'btn btn-danger']) ?> + ' ?> +
diff --git a/src/UseCase/Users/List/Action.php b/src/UseCase/Users/List/Action.php new file mode 100644 index 0000000000000..63f89077ab1e8 --- /dev/null +++ b/src/UseCase/Users/List/Action.php @@ -0,0 +1,25 @@ +hasHeader('Hx-Request')) { + return $this->responseFactory->createHtmlResponse(UsersList::widget()); + } + + return $this->responseFactory->render(__DIR__ . '/template.php'); + } +} diff --git a/src/UseCase/Users/List/DataReader/User.php b/src/UseCase/Users/List/DataReader/User.php new file mode 100644 index 0000000000000..f3f7c72dc211b --- /dev/null +++ b/src/UseCase/Users/List/DataReader/User.php @@ -0,0 +1,22 @@ + + */ +final class UserDataReader extends QueryDataReader +{ + public function __construct( + ConnectionInterface $db, + ManagerInterface $rbacManager, + ) { + parent::__construct( + $db->createQuery() + ->select(['id', 'login', 'name', 'status']) + ->from('user') + ->resultCallback( + static function (array $rows) use ($rbacManager): array { + /** + * @var non-empty-list $rows + * @var list $userIds + */ + return array_map( + static function (array $row) use ($rbacManager) { + $userId = (int) $row['id']; + $roles = array_map( + static fn(RbacRole $rbacRole) => Role::from($rbacRole->getName()), + $rbacManager->getRolesByUserId($userId), + ); + return new User( + id: $userId, + login: $row['login'], + name: $row['name'], + status: UserStatus::from((int) $row['status']), + roles: $roles, + ); + }, + $rows, + ); + }, + ), + Sort::only(['id', 'login', 'name', 'status'])->withOrder(['id' => 'desc']), + ); + } +} diff --git a/src/UseCase/Users/List/UsersList.php b/src/UseCase/Users/List/UsersList.php new file mode 100644 index 0000000000000..a29182b57eaa5 --- /dev/null +++ b/src/UseCase/Users/List/UsersList.php @@ -0,0 +1,110 @@ + '#UsersGridView', + 'hx-target' => '#UsersGridView', + 'hx-replace-url' => 'true', + 'hx-swap' => 'outerHTML', + ]; + + /** @var PaginationWidgetInterface */ + $pagination = OffsetPagination::widget()->addLinkAttributes([ + 'hx-boost' => 'true', + ...$htmxLoadAttributes, + ]); + + return GridView::widget() + ->containerAttributes([ + 'id' => 'UsersGridView', + 'class' => 'mt-4 position-relative', + ]) + ->dataReader($this->userDataReader) + ->sortableLinkAttributes([ + 'hx-boost' => 'true', + ...$htmxLoadAttributes, + ]) + ->filterFormAttributes([ + 'hx-boost' => 'true', + ...$htmxLoadAttributes, + ]) + ->paginationWidget($pagination) + ->columns( + new DataColumn( + 'id', + header: 'ID', + filter: true, + ), + new DataColumn( + 'login', + filter: true, + ), + new DataColumn( + 'name', + filter: true, + ), + new DataColumn( + 'status', + content: static fn(User $user) => $user->status->label(), + ), + new DataColumn( + 'roles', + header: 'Role', + content: static fn(User $user) => implode( + ', ', + array_map( + static fn($role) => $role->label(), + $user->roles, + ), + ), + ), + new ActionColumn( + before: '
', + after: '
', + buttons: [ + new ActionButton( + Html::i()->class('bi bi-pencil'), + fn(User $user) => $this->urlGenerator->generate('user/update', ['id' => $user->id]), + title: 'Update', + ), + new ActionButton( + Html::i()->class('bi bi-key'), + fn(User $user) => $this->urlGenerator->generate('user/change-password', ['id' => $user->id]), + title: 'Change password', + ), + new ActionButton( + Html::i()->class('bi bi-x-lg'), + fn(User $user) => $this->urlGenerator->generate('user/delete', ['id' => $user->id]), + title: 'Delete', + ), + ], + ), + ) + ->render(); + } +} diff --git a/src/UseCase/Users/List/template.php b/src/UseCase/Users/List/template.php new file mode 100644 index 0000000000000..b101c84d10994 --- /dev/null +++ b/src/UseCase/Users/List/template.php @@ -0,0 +1,28 @@ +setTitle('Users'); +$this->addToParameter('breadcrumbs', new Breadcrumb('Users')); +?> +
+

Users

+ Create user'), + $urlGenerator->generate('user/create'), + ['class' => 'btn btn-outline-primary btn-sm'], + ) ?> +
+ diff --git a/src/UseCase/Users/Update/Action.php b/src/UseCase/Users/Update/Action.php new file mode 100644 index 0000000000000..1df75cbf79153 --- /dev/null +++ b/src/UseCase/Users/Update/Action.php @@ -0,0 +1,110 @@ +findByPk($userId) ?? throw new UserException('User not found.'); + + /** @var \Yiisoft\Rbac\Role|null $currentYiiRole */ + $currentYiiRole = array_first($this->rbacManager->getRolesByUserId($userId)); + $currentRole = $currentYiiRole === null ? null : Role::from($currentYiiRole->getName()); + $form = new Form( + $user, + $currentRole, + $this->authenticatedUserProvider->getId() === $user->getId(), + ); + + if (!$this->formHydrator->populateFromPostAndValidate($form, $request)) { + return $this->renderForm($form); + } + + /** + * @var Role $role + */ + $role = $form->role; + + if ($form->isCurrentUser) { + if ($form->status !== $user->status) { + throw new UserException('Cannot change status for current user.'); + } + if ($role !== $currentRole) { + throw new UserException('Cannot change role for current user.'); + } + } + + if ($user->login !== $form->login + && User::query()->where(['login' => $form->login])->exists() + ) { + $form->addError( + sprintf('User with login "%s" already exist.', $form->login), + valuePath: ['login'], + ); + return $this->renderForm($form); + } + + $user->login = $form->login; + $user->name = $form->name; + $user->status = $form->status; + $this->db->transaction( + function () use ($user, $role) { + $user->save(); + $this->rbacManager->revokeAll($user->getId()); + $this->rbacManager->assign($role->value, $user->getId()); + }, + ); + + $this->contentNotices->success( + sprintf( + 'User "%s" is updated.', + $form->login, + ), + ); + return $this->responseFactory->temporarilyRedirect($this->urlGenerator->generate('user/index')); + } + + private function renderForm(Form $form): ResponseInterface + { + return $this->responseFactory->render( + __DIR__ . '/template.php', + ['form' => $form], + ); + } +} diff --git a/src/UseCase/Users/Update/Form.php b/src/UseCase/Users/Update/Form.php new file mode 100644 index 0000000000000..7782e8e89c5c0 --- /dev/null +++ b/src/UseCase/Users/Update/Form.php @@ -0,0 +1,38 @@ +login = $user->login; + $this->name = $user->name; + $this->status = $user->status; + } +} diff --git a/src/UseCase/Users/Update/template.php b/src/UseCase/Users/Update/template.php new file mode 100644 index 0000000000000..5e5d343c809e8 --- /dev/null +++ b/src/UseCase/Users/Update/template.php @@ -0,0 +1,56 @@ +setTitle('Update user'); +$this->addToParameter( + 'breadcrumbs', + new Breadcrumb('Users', $urlGenerator->generate('user/index')), + new Breadcrumb('Update user'), +); + +$field = new FieldFactory(); +?> +

Update User

+
+
+ user]) ?> + errorSummary($form)->onlyCommonErrors() ?> + post($urlGenerator->generate('user/update', ['id' => $form->user->getId()])) + ->csrf($csrf) + ->open() ?> + text($form, 'login') ?> + text($form, 'name') ?> + select($form, 'status') + ->optionsData(UserStatus::labelsByValue()) + ->disabled($form->isCurrentUser) +?> + select($form, 'role') + ->optionsData(Role::labelsByValue()) + ->disabled($form->isCurrentUser) +?> + submitButton('Save')->afterInput( + Html::a('Cancel', $urlGenerator->generate('user/index'), ['class' => 'btn btn-outline-secondary ms-2']), + ) ?> + ' ?> +
+
diff --git a/src/autoload.php b/src/autoload.php new file mode 100644 index 0000000000000..25b3c9c28f417 --- /dev/null +++ b/src/autoload.php @@ -0,0 +1,12 @@ +load(); +Environment::prepare(); diff --git a/tests/.env b/tests/.env new file mode 100644 index 0000000000000..1b5934023eb26 --- /dev/null +++ b/tests/.env @@ -0,0 +1,2 @@ +APP_ENV=test +APP_DEBUG=true diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000000000..c3ef3ab84dc97 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +/_output diff --git a/tests/Console.suite.yml b/tests/Console.suite.yml new file mode 100644 index 0000000000000..34667513370c6 --- /dev/null +++ b/tests/Console.suite.yml @@ -0,0 +1,4 @@ +actor: ConsoleTester +modules: + enabled: + - Cli diff --git a/tests/Console/YiiCest.php b/tests/Console/YiiCest.php new file mode 100644 index 0000000000000..aa9435db12b42 --- /dev/null +++ b/tests/Console/YiiCest.php @@ -0,0 +1,17 @@ +runApp(); + $I->canSeeResultCodeIs(0); + $I->seeInShellOutput('Yii Console'); + } +} diff --git a/tests/Functional.suite.yml b/tests/Functional.suite.yml new file mode 100644 index 0000000000000..bcfdb6d2dba0f --- /dev/null +++ b/tests/Functional.suite.yml @@ -0,0 +1 @@ +actor: FunctionalTester diff --git a/tests/Functional/HomePageCest.php b/tests/Functional/HomePageCest.php new file mode 100644 index 0000000000000..ec722f2d7e942 --- /dev/null +++ b/tests/Functional/HomePageCest.php @@ -0,0 +1,27 @@ +sendSiteRequest( + new ServerRequest(uri: '/'), + ); + + assertSame(200, $response->getStatusCode()); + assertStringContainsString( + 'Welcome to Yii3 Demo Diary', + $response->getBody()->getContents(), + ); + } +} diff --git a/tests/Site.suite.yml b/tests/Site.suite.yml new file mode 100644 index 0000000000000..d8ac7b47c6fe1 --- /dev/null +++ b/tests/Site.suite.yml @@ -0,0 +1,10 @@ +actor: SiteTester +extensions: + enabled: + - Codeception\Extension\RunProcess: + 0: composer serve + sleep: 3 +modules: + enabled: + - PhpBrowser: + url: http://127.0.0.1:8080 diff --git a/tests/Site/HomePageCest.php b/tests/Site/HomePageCest.php new file mode 100644 index 0000000000000..f8e220ecb9ef5 --- /dev/null +++ b/tests/Site/HomePageCest.php @@ -0,0 +1,18 @@ +wantTo('home page works.'); + $I->amOnPage('/'); + $I->expectTo('see page home.'); + $I->see('Welcome to Yii3 Demo Diary'); + } +} diff --git a/tests/Site/NotFoundHandlerCest.php b/tests/Site/NotFoundHandlerCest.php new file mode 100644 index 0000000000000..ee61f3fad9ef4 --- /dev/null +++ b/tests/Site/NotFoundHandlerCest.php @@ -0,0 +1,28 @@ +wantTo('see 404 page.'); + $I->amOnPage('/non-existent-page'); + $I->canSeeResponseCodeIs(404); + $I->see('Page not found'); + } + + public function returnHome(SiteTester $I): void + { + $I->wantTo('check "Go Back Home" link.'); + $I->amOnPage('/non-existent-page'); + $I->canSeeResponseCodeIs(404); + $I->click('Go Back Home'); + $I->expectTo('see page home.'); + $I->see('Welcome to Yii3 Demo Diary'); + } +} diff --git a/tests/Support/ConsoleTester.php b/tests/Support/ConsoleTester.php new file mode 100644 index 0000000000000..2fab4716c2d59 --- /dev/null +++ b/tests/Support/ConsoleTester.php @@ -0,0 +1,38 @@ +runShellCommand( + dirname(__DIR__, 2) . '/yii' . ($parameters === null ? '' : (' ' . $parameters)), + ); + } +} diff --git a/tests/Support/Data/.gitkeep b/tests/Support/Data/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/Support/FunctionalTester.php b/tests/Support/FunctionalTester.php new file mode 100644 index 0000000000000..f8147907b73c7 --- /dev/null +++ b/tests/Support/FunctionalTester.php @@ -0,0 +1,63 @@ +runAndGetResponse($request); + + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + + return $response; + } +} diff --git a/tests/Support/SiteTester.php b/tests/Support/SiteTester.php new file mode 100644 index 0000000000000..39735e42fd6cf --- /dev/null +++ b/tests/Support/SiteTester.php @@ -0,0 +1,29 @@ +run(); diff --git a/yii.bat b/yii.bat new file mode 100644 index 0000000000000..cdb29a68f5033 --- /dev/null +++ b/yii.bat @@ -0,0 +1,6 @@ +@echo off +@setlocal +set YII_PATH=%~dp0 +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php +"%PHP_COMMAND%" "%YII_PATH%yii" %* +@endlocal