diff --git a/.env.ci b/.env.ci new file mode 100644 index 0000000..004c0f0 --- /dev/null +++ b/.env.ci @@ -0,0 +1 @@ +DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" \ No newline at end of file diff --git a/.env.dist b/.env.dist new file mode 100644 index 0000000..0c9b7ae --- /dev/null +++ b/.env.dist @@ -0,0 +1,30 @@ +# In all environments, the following files are loaded if they exist, +# the latter taking precedence over the former: +# +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# https://symfony.com/doc/current/configuration/secrets.html +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). +# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=329c08089dae58b62725c9bd011e847c +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml +# +DATABASE_URL= +# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" +###< doctrine/doctrine-bundle ### diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..391eae1 --- /dev/null +++ b/.env.test @@ -0,0 +1,11 @@ +# define your env variables for the test env here +KERNEL_CLASS='App\Kernel' +APP_SECRET='$ecretf0rt3st' +SYMFONY_DEPRECATIONS_HELPER=999999 +PANTHER_APP_ENV=panther +PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots + +DATABASE_URL="mysql://root:password@127.0.0.1:3306/qanightlyresults?serverVersion=8.0.23&charset=utf8mb4" + +QANB_GCPURL=https://storage.googleapis.com/prestashop-core-nightly/ +QANB_TOKEN='AZERTY' \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5c83b81 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: composer + directory: "/" + schedule: + interval: weekly + day: monday + time: "04:00" + open-pull-requests-limit: 10 + target-branch: develop + reviewers: + - "PrestaShop/ui-tests-maintainers" + labels: + - "dependencies" \ No newline at end of file diff --git a/.github/workflows/integration-cd.yml b/.github/workflows/integration-cd.yml index 494b650..9d47a4e 100644 --- a/.github/workflows/integration-cd.yml +++ b/.github/workflows/integration-cd.yml @@ -26,7 +26,7 @@ jobs: - name: Get branch name id: branch - uses: tj-actions/branch-names@v5.1 + uses: tj-actions/branch-names@v7.0.7 - name: Trigger CI / CD uses: aurelien-baudet/workflow-dispatch@v2 diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..4d719e4 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,118 @@ +name: PHP +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + php-cs-fixer: + permissions: + contents: read # for actions/checkout to fetch code + name: PHP CS Fixer + runs-on: ubuntu-latest + env: + APP_ENV: ci + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v3 + + - name: Config + run: cp .env.dist .env + + - name: Validate composer config + run: composer validate --strict + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run PHPCSFixer + run: ./vendor/bin/php-cs-fixer fix --dry-run --diff + + - name: Run ergebnis/composer-normalize + run: composer normalize --dry-run --no-check-lock + phpstan: + permissions: + contents: read # for actions/checkout to fetch code + name: PHP Static Analysis + runs-on: ubuntu-latest + env: + APP_ENV: ci + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/checkout@v3 + + - name: Config + run: cp .env.dist .env + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpstan + run: ./vendor/bin/phpstan analyse + phpunit: + permissions: + contents: read # for actions/checkout to fetch code + name: PHPUnit + runs-on: ubuntu-latest + env: + APP_ENV: test + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup MySQL + uses: mirromutth/mysql-action@v1.1 + with: + mysql version: '8.0' + mysql database: 'qanightlyresults' + mysql root password: 'password' + + - uses: actions/checkout@v3 + + - name: Config + run: cp .env.dist .env + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Change MySQL authentication method + run: sleep 15 && mysql -h127.0.0.1 -uroot -ppassword -e "ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password'; FLUSH PRIVILEGES;" + + - name: Setup database + run: php bin/console doctrine:schema:update --dump-sql --force --env=test + + - name: Inject data for AutoUpgrade + run: | + DATE=$(date -d "2 days ago" +"%Y-%m-%d") + php bin/console nightly:import autoupgrade_$DATE-develop.json\ + -p cli \ + -c autoupgrade \ + --env test + + - name: Inject data for Core + run: | + DATE=$(date -d "2 days ago" +"%Y-%m-%d") + php bin/console nightly:import $DATE-develop.json\ + -p chromium \ + -c functional \ + --env test + + - name: Run phpunit + run: ./vendor/bin/phpunit \ No newline at end of file diff --git a/.github/workflows/preproduction-cd.yml b/.github/workflows/preproduction-cd.yml index 2e90b17..39704e4 100644 --- a/.github/workflows/preproduction-cd.yml +++ b/.github/workflows/preproduction-cd.yml @@ -18,7 +18,7 @@ jobs: - name: Get branch name id: branch - uses: tj-actions/branch-names@v5.1 + uses: tj-actions/branch-names@v7.0.7 - name: Trigger CI / CD uses: aurelien-baudet/workflow-dispatch@v2 diff --git a/.github/workflows/production-cd.yml b/.github/workflows/production-cd.yml index 2ce1f76..9ce0879 100644 --- a/.github/workflows/production-cd.yml +++ b/.github/workflows/production-cd.yml @@ -17,7 +17,7 @@ jobs: - name: Get branch name id: branch - uses: tj-actions/branch-names@v5.1 + uses: tj-actions/branch-names@v7.0.7 - name: Trigger CI / CD uses: aurelien-baudet/workflow-dispatch@v2 diff --git a/.gitignore b/.gitignore index 0a6b75c..3f1e4db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,29 @@ -.idea/ -vendor/** -.php_cs.cache + +###> symfony/framework-bundle ### +/.env +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> symfony/phpunit-bridge ### +.phpunit.result.cache +/phpunit.xml +###< symfony/phpunit-bridge ### + +###> phpunit/phpunit ### +/phpunit.xml +.phpunit.result.cache +###< phpunit/phpunit ### + +###> friendsofphp/php-cs-fixer ### +/.php-cs-fixer.php +/.php-cs-fixer.cache +###< friendsofphp/php-cs-fixer ### + +###> phpstan/phpstan ### +###< phpstan/phpstan ### diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..ac60bc2 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,48 @@ +in([ + __DIR__.'/src', + __DIR__.'/migrations', + __DIR__.'/public', + __DIR__.'/tests', +]); + +return (new PhpCsFixer\Config()) + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + 'array_indentation' => true, + 'cast_spaces' => [ + 'space' => 'single', + ], + 'combine_consecutive_issets' => true, + 'concat_space' => [ + 'spacing' => 'one', + ], + 'error_suppression' => [ + 'mute_deprecation_error' => false, + 'noise_remaining_usages' => false, + 'noise_remaining_usages_exclude' => [], + ], + 'function_to_constant' => false, + 'method_chaining_indentation' => true, + 'no_alias_functions' => false, + 'no_superfluous_phpdoc_tags' => false, + 'non_printable_character' => [ + 'use_escape_sequences_in_strings' => true, + ], + 'phpdoc_align' => [ + 'align' => 'left', + ], + 'phpdoc_summary' => false, + 'protected_to_private' => false, + 'psr_autoloading' => false, + 'self_accessor' => false, + 'yoda_style' => false, + 'single_line_throw' => false, + 'no_alias_language_construct_call' => false, + ]) + ->setFinder($finder) + ->setCacheFile(__DIR__.'/var/.php_cs.cache'); \ No newline at end of file diff --git a/.php_cs.dist b/.php_cs.dist deleted file mode 100644 index 9830d6d..0000000 --- a/.php_cs.dist +++ /dev/null @@ -1,11 +0,0 @@ -setUsingCache(true) - ->getFinder() - ->in(__DIR__) - ->exclude('vendor'); - -return $config; diff --git a/Dockerfile b/Dockerfile index 66b892a..b9d5211 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.2-apache as builder +FROM php:8.3-apache as builder RUN apt-get update && \ apt-get install -y \ @@ -15,7 +15,7 @@ RUN composer update && \ composer install -FROM php:7.2-apache +FROM php:8.3-apache RUN apt-get update && \ apt-get install -y \ @@ -42,4 +42,5 @@ RUN mv /var/www/html/vhost.conf /etc/apache2/sites-enabled/000-default.conf && \ a2enmod headers RUN sed -i 's/^max_execution_time = .*/max_execution_time = 300/' /usr/local/etc/php/php.ini-production && \ + sed -i 's/variables_order = "GPCS"/variables_order = "EGPCS"/' /usr/local/etc/php/php.ini-production && \ mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" diff --git a/README.md b/README.md index 7ad5aae..0fbf53b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # QANightlyResults -QANightlyResults is a Slim Framework app, acting as a backend (via a JSON API) to handle -and browse tests reports records. +QANightlyResults is a Symfony app, acting as a backend (via a JSON API) to handle and browse tests reports records. You can use any frontend app you want to consume this API. We use a [Vue app](https://github.com/PrestaShop/nightly-board). @@ -18,6 +17,10 @@ Don't forget to launch `composer install` to install all dependencies. ### Configuration +You can create a `.env.local` file at the root of the project. + +### Configuration + You can edit the `settings.php` file in the `src/` folder (no recommended). You can also pass the values via environment variables. Here are the main ones: |Variables | | diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..c933dc5 --- /dev/null +++ b/bin/console @@ -0,0 +1,17 @@ +#!/usr/bin/env php += 80000) { + require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit'; + } else { + define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php'); + require PHPUNIT_COMPOSER_INSTALL; + PHPUnit\TextUI\Command::main(); + } +} else { + if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) { + echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n"; + exit(1); + } + + require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php'; +} diff --git a/bootstrap.php b/bootstrap.php deleted file mode 100644 index 8a41de6..0000000 --- a/bootstrap.php +++ /dev/null @@ -1,15 +0,0 @@ -=8.2", + "ext-ctype": "*", + "ext-iconv": "*", + "beberlei/doctrineextensions": "^1.3", + "doctrine/doctrine-bundle": "^2.11", + "doctrine/doctrine-migrations-bundle": "^3.3", + "doctrine/orm": "^2.17", + "symfony/apache-pack": "^1.0", + "symfony/console": "~7.0.0", + "symfony/dotenv": "~7.0.0", + "symfony/flex": "^2", + "symfony/framework-bundle": "~7.0.0", + "symfony/runtime": "~7.0.0", + "symfony/yaml": "~7.0.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.41", + "friendsofphp/php-cs-fixer": "^3.45", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "symfony/browser-kit": "~7.0.0", + "symfony/css-selector": "~7.0.0", + "symfony/maker-bundle": "^1.52", + "symfony/phpunit-bridge": "^7.0" + }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php82": "*" + }, + "conflict": { + "symfony/symfony": "*" + }, + "minimum-stability": "stable", + "prefer-stable": true, "autoload": { "psr-4": { "App\\": "src/" } }, - "require": { - "php": ">=7.1", - "ext-json": "*", - "ext-simplexml": "*", - "slim/slim": "4.*", - "slim/psr7": "^1.0.0", - "php-di/slim-bridge": "^3.0", - "illuminate/database": "^6.8" + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } }, - "require-dev": { - "prestashop/php-dev-tools": "^4.0", - "phpstan/phpstan": "^0.12.88" + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true, + "php-http/discovery": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "sort-packages": true + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "7.0.*" + } + }, + "scripts": { + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ], + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + } } } diff --git a/composer.lock b/composer.lock index 5c70781..4a44593 100644 --- a/composer.lock +++ b/composer.lock @@ -4,41 +4,97 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "118e4b28a431493b9f859382039f9fe2", + "content-hash": "8aa52e11b69349009c54d3eb9bc89594", "packages": [ { - "name": "doctrine/inflector", - "version": "2.0.3", + "name": "beberlei/doctrineextensions", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210" + "url": "https://github.com/beberlei/DoctrineExtensions.git", + "reference": "008f162f191584a6c37c03a803f718802ba9dd9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210", - "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210", + "url": "https://api.github.com/repos/beberlei/DoctrineExtensions/zipball/008f162f191584a6c37c03a803f718802ba9dd9a", + "reference": "008f162f191584a6c37c03a803f718802ba9dd9a", "shasum": "" }, "require": { + "doctrine/orm": "^2.7", "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^7.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "friendsofphp/php-cs-fixer": "^2.14", + "nesbot/carbon": "*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "symfony/yaml": "^4.2 || ^5.0", + "zf1/zend-date": "^1.12", + "zf1/zend-registry": "^1.12" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" + "autoload": { + "psr-4": { + "DoctrineExtensions\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Steve Lacey", + "email": "steve@steve.ly" } + ], + "description": "A set of extensions to Doctrine 2 that add support for additional query functions available in MySQL, Oracle, PostgreSQL and SQLite.", + "keywords": [ + "database", + "doctrine", + "orm" + ], + "support": { + "source": "https://github.com/beberlei/DoctrineExtensions/tree/v1.3.0" + }, + "time": "2020-11-29T07:37:23+00:00" + }, + { + "name": "doctrine/cache", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" }, + "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -67,23 +123,22 @@ "email": "schmittjoh@gmail.com" } ], - "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", - "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", "php", - "plural", - "singular", - "strings", - "uppercase", - "words" + "redis", + "xcache" ], "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.x" + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" }, "funding": [ { @@ -95,41 +150,42 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", "type": "tidelift" } ], - "time": "2020-05-29T15:13:26+00:00" + "time": "2022-05-20T20:07:39+00:00" }, { - "name": "fig/http-message-util", - "version": "1.1.5", + "name": "doctrine/collections", + "version": "2.1.4", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message-util.git", - "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" + "url": "https://github.com/doctrine/collections.git", + "reference": "72328a11443a0de79967104ad36ba7b30bded134" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", - "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "url": "https://api.github.com/repos/doctrine/collections/zipball/72328a11443a0de79967104ad36ba7b30bded134", + "reference": "72328a11443a0de79967104ad36ba7b30bded134", "shasum": "" }, "require": { - "php": "^5.3 || ^7.0 || ^8.0" + "doctrine/deprecations": "^1", + "php": "^8.1" }, - "suggest": { - "psr/http-message": "The package containing the PSR-7 interfaces" + "require-dev": { + "doctrine/coding-standard": "^12", + "ext-json": "*", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.11" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, "autoload": { "psr-4": { - "Fig\\Http\\Message\\": "src/" + "Doctrine\\Common\\Collections\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -138,101 +194,86 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "array", + "collections", + "iterators", + "php" ], "support": { - "issues": "https://github.com/php-fig/http-message-util/issues", - "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" - }, - "time": "2020-11-24T22:02:12+00:00" - }, - { - "name": "illuminate/container", - "version": "v6.20.26", - "source": { - "type": "git", - "url": "https://github.com/illuminate/container.git", - "reference": "aa6e7030cba7458bbeeddfb1ddb54b3c2f7ba113" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/aa6e7030cba7458bbeeddfb1ddb54b3c2f7ba113", - "reference": "aa6e7030cba7458bbeeddfb1ddb54b3c2f7ba113", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^6.0", - "php": "^7.2.5|^8.0", - "psr/container": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Illuminate\\Container\\": "" - } + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/2.1.4" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections", + "type": "tidelift" } ], - "description": "The Illuminate Container package.", - "homepage": "https://laravel.com", - "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" - }, - "time": "2020-10-27T16:13:38+00:00" + "time": "2023-10-03T09:22:33+00:00" }, { - "name": "illuminate/contracts", - "version": "v6.20.26", + "name": "doctrine/common", + "version": "3.4.3", "source": { "type": "git", - "url": "https://github.com/illuminate/contracts.git", - "reference": "89dc8d7ac32cdfa254461cdd4da5d692b44169a4" + "url": "https://github.com/doctrine/common.git", + "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/89dc8d7ac32cdfa254461cdd4da5d692b44169a4", - "reference": "89dc8d7ac32cdfa254461cdd4da5d692b44169a4", + "url": "https://api.github.com/repos/doctrine/common/zipball/8b5e5650391f851ed58910b3e3d48a71062eeced", + "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced", "shasum": "" }, "require": { - "php": "^7.2.5|^8.0", - "psr/container": "^1.0", - "psr/simple-cache": "^1.0" + "doctrine/persistence": "^2.0 || ^3.0", + "php": "^7.1 || ^8.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } + "require-dev": { + "doctrine/coding-standard": "^9.0 || ^10.0", + "doctrine/collections": "^1", + "phpstan/phpstan": "^1.4.1", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^6.1", + "vimeo/psalm": "^4.4" }, + "type": "library", "autoload": { "psr-4": { - "Illuminate\\Contracts\\": "" + "Doctrine\\Common\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -241,57 +282,104 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], - "description": "The Illuminate Contracts package.", - "homepage": "https://laravel.com", + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/doctrine/common/issues", + "source": "https://github.com/doctrine/common/tree/3.4.3" }, - "time": "2020-12-18T14:12:37+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", + "type": "tidelift" + } + ], + "time": "2022-10-09T11:47:59+00:00" }, { - "name": "illuminate/database", - "version": "v6.20.26", + "name": "doctrine/dbal", + "version": "3.7.2", "source": { "type": "git", - "url": "https://github.com/illuminate/database.git", - "reference": "8445174d134a37d921ee07ff1289e44dcc6a47db" + "url": "https://github.com/doctrine/dbal.git", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/8445174d134a37d921ee07ff1289e44dcc6a47db", - "reference": "8445174d134a37d921ee07ff1289e44dcc6a47db", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", "shasum": "" }, "require": { - "ext-json": "*", - "illuminate/container": "^6.0", - "illuminate/contracts": "^6.0", - "illuminate/support": "^6.0", - "php": "^7.2.5|^8.0" + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "12.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.1", + "phpstan/phpstan": "1.10.42", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "9.6.13", + "psalm/plugin-phpunit": "0.18.4", + "slevomat/coding-standard": "8.13.1", + "squizlabs/php_codesniffer": "3.7.2", + "symfony/cache": "^5.4|^6.0", + "symfony/console": "^4.4|^5.4|^6.0", + "vimeo/psalm": "4.30.0" }, "suggest": { - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", - "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", - "illuminate/console": "Required to use the database commands (^6.0).", - "illuminate/events": "Required to use the observers with Eloquent (^6.0).", - "illuminate/filesystem": "Required to use the migrations (^6.0).", - "illuminate/pagination": "Required to paginate the result set (^6.0).", - "symfony/finder": "Required to use Eloquent model factories (^4.3.4)." + "symfony/console": "For helpful console commands such as SQL execution and import of files." }, + "bin": [ + "bin/doctrine-dbal" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, "autoload": { "psr-4": { - "Illuminate\\Database\\": "" + "Doctrine\\DBAL\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -300,142 +388,178 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" } ], - "description": "The Illuminate Database package.", - "homepage": "https://laravel.com", + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", "keywords": [ + "abstraction", "database", - "laravel", - "orm", - "sql" + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" ], "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.7.2" }, - "time": "2021-04-28T13:18:19+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2023-11-19T08:06:58+00:00" }, { - "name": "illuminate/support", - "version": "v6.20.26", + "name": "doctrine/deprecations", + "version": "1.1.2", "source": { "type": "git", - "url": "https://github.com/illuminate/support.git", - "reference": "566e3dcfb0e3973ed8cd86ddb4ad4ef33a84fedf" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/566e3dcfb0e3973ed8cd86ddb4ad4ef33a84fedf", - "reference": "566e3dcfb0e3973ed8cd86ddb4ad4ef33a84fedf", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", "shasum": "" }, "require": { - "doctrine/inflector": "^1.4|^2.0", - "ext-json": "*", - "ext-mbstring": "*", - "illuminate/contracts": "^6.0", - "nesbot/carbon": "^2.31", - "php": "^7.2.5|^8.0" + "php": "^7.1 || ^8.0" }, - "conflict": { - "tightenco/collect": "<5.5.33" + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { - "illuminate/filesystem": "Required to use the composer class (^6.0).", - "moontoast/math": "Required to use ordered UUIDs (^1.1).", - "ramsey/uuid": "Required to use Str::uuid() (^3.7).", - "symfony/process": "Required to use the composer class (^4.3.4).", - "symfony/var-dumper": "Required to use the dd function (^4.3.4).", - "vlucas/phpdotenv": "Required to use the Env class and env helper (^3.3)." + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, "autoload": { "psr-4": { - "Illuminate\\Support\\": "" - }, - "files": [ - "helpers.php" - ] + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "The Illuminate Support package.", - "homepage": "https://laravel.com", + "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/laravel/framework/issues", - "source": "https://github.com/laravel/framework" + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" }, - "time": "2021-03-12T13:52:50+00:00" + "time": "2023-09-27T20:04:15+00:00" }, { - "name": "nesbot/carbon", - "version": "2.46.0", + "name": "doctrine/doctrine-bundle", + "version": "2.11.1", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4" + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "4089f1424b724786c062aea50aae5f773449b94b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4", - "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/4089f1424b724786c062aea50aae5f773449b94b", + "reference": "4089f1424b724786c062aea50aae5f773449b94b", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.1.8 || ^8.0", - "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^3.4 || ^4.0 || ^5.0" + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/dbal": "^3.7.0 || ^4.0", + "doctrine/persistence": "^2.2 || ^3", + "doctrine/sql-formatter": "^1.0.1", + "php": "^7.4 || ^8.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" + }, + "conflict": { + "doctrine/annotations": ">=3.0", + "doctrine/orm": "<2.14 || >=4.0", + "twig/twig": "<1.34 || >=2.0 <2.4" }, "require-dev": { - "doctrine/orm": "^2.7", - "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", - "kylekatarnls/multi-tester": "^2.0", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.54", - "phpunit/phpunit": "^7.5.20 || ^8.5.14", - "squizlabs/php_codesniffer": "^3.4" + "doctrine/annotations": "^1 || ^2", + "doctrine/coding-standard": "^12", + "doctrine/deprecations": "^1.0", + "doctrine/orm": "^2.14 || ^3.0", + "friendsofphp/proxy-manager-lts": "^1.0", + "phpunit/phpunit": "^9.5.26 || ^10.0", + "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-symfony": "^4", + "psr/log": "^1.1.4 || ^2.0 || ^3.0", + "symfony/phpunit-bridge": "^6.1 || ^7.0", + "symfony/property-info": "^5.4 || ^6.0 || ^7.0", + "symfony/proxy-manager-bridge": "^5.4 || ^6.0 || ^7.0", + "symfony/security-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/string": "^5.4 || ^6.0 || ^7.0", + "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^5.4 || ^6.2 || ^7.0", + "symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", + "twig/twig": "^1.34 || ^2.12 || ^3.0", + "vimeo/psalm": "^4.30" }, - "bin": [ - "bin/carbon" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev", - "dev-3.x": "3.x-dev" - }, - "laravel": { - "providers": [ - "Carbon\\Laravel\\ServiceProvider" - ] - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "ext-pdo": "*", + "symfony/web-profiler-bundle": "To use the data collector." }, + "type": "symfony-bundle", "autoload": { "psr-4": { - "Carbon\\": "src/Carbon/" + "Doctrine\\Bundle\\DoctrineBundle\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -444,121 +568,3545 @@ ], "authors": [ { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "http://nesbot.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" }, { - "name": "kylekatarnls", - "homepage": "http://github.com/kylekatarnls" + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org/" } ], - "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "http://carbon.nesbot.com", + "description": "Symfony DoctrineBundle", + "homepage": "https://www.doctrine-project.org", "keywords": [ - "date", - "datetime", - "time" + "database", + "dbal", + "orm", + "persistence" ], "support": { - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" + "issues": "https://github.com/doctrine/DoctrineBundle/issues", + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.1" }, "funding": [ { - "url": "https://opencollective.com/Carbon", - "type": "open_collective" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", "type": "tidelift" } ], - "time": "2021-02-24T17:30:44+00:00" + "time": "2023-11-15T20:01:50+00:00" }, { - "name": "nikic/fast-route", - "version": "v1.3.0", + "name": "doctrine/doctrine-migrations-bundle", + "version": "3.3.0", "source": { "type": "git", - "url": "https://github.com/nikic/FastRoute.git", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", + "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1dd42906a5fb9c5960723e2ebb45c68006493835", + "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835", "shasum": "" }, "require": { - "php": ">=5.4.0" + "doctrine/doctrine-bundle": "^2.4", + "doctrine/migrations": "^3.2", + "php": "^7.2|^8.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|~5.7" + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.6 || ^3", + "doctrine/persistence": "^2.0 || ^3 ", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^8.5|^9.5", + "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-symfony": "^3 || ^5", + "symfony/phpunit-bridge": "^6.3 || ^7", + "symfony/var-exporter": "^5.4 || ^6 || ^7", + "vimeo/psalm": "^4.30 || ^5.15" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\MigrationsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineMigrationsBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "dbal", + "migrations", + "schema" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2023-11-13T19:44:41+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2022-10-12T20:59:15+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.8", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.8" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2023-06-16T13:40:37+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-14T08:49:07+00:00" + }, + { + "name": "doctrine/migrations", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a", + "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.5.1 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.2 || ^7.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^10.3", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "dbal", + "migrations" + ], + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.7.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2023-12-05T11:35:05+00:00" + }, + { + "name": "doctrine/orm", + "version": "2.17.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "393679a4795e49b0b3ac317dce84d0f8888f2b77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/393679a4795e49b0b3ac317dce84d0f8888f2b77", + "reference": "393679a4795e49b0b3ac317dce84d0f8888f2b77", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.12.1 || ^2.1.1", + "doctrine/collections": "^1.5 || ^2.1", + "doctrine/common": "^3.0.3", + "doctrine/dbal": "^2.13.1 || ^3.2", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2", + "doctrine/inflector": "^1.4 || ^2.0", + "doctrine/instantiator": "^1.3 || ^2", + "doctrine/lexer": "^2", + "doctrine/persistence": "^2.4 || ^3", + "ext-ctype": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3", + "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0", + "symfony/polyfill-php72": "^1.23", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "doctrine/annotations": "<1.13 || >= 3.0" + }, + "require-dev": { + "doctrine/annotations": "^1.13 || ^2", + "doctrine/coding-standard": "^9.0.2 || ^12.0", + "phpbench/phpbench": "^0.16.10 || ^1.0", + "phpstan/phpstan": "~1.4.10 || 1.10.35", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "psr/log": "^1 || ^2 || ^3", + "squizlabs/php_codesniffer": "3.7.2", + "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "vimeo/psalm": "4.30.0 || 5.16.0" + }, + "suggest": { + "ext-dom": "Provides support for XSD validation for XML mapping files", + "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0", + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ], + "support": { + "issues": "https://github.com/doctrine/orm/issues", + "source": "https://github.com/doctrine/orm/tree/2.17.2" + }, + "time": "2023-12-20T21:47:52+00:00" + }, + { + "name": "doctrine/persistence", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "63fee8c33bef740db6730eb2a750cd3da6495603" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603", + "reference": "63fee8c33bef740db6730eb2a750cd3da6495603", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "^1 || ^2", + "php": "^7.2 || ^8.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0" + }, + "conflict": { + "doctrine/common": "<2.10" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/coding-standard": "^11", + "doctrine/common": "^3.0", + "phpstan/phpstan": "1.9.4", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0", + "vimeo/psalm": "4.30.0 || 5.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Persistence\\": "src/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://www.doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/persistence/issues", + "source": "https://github.com/doctrine/persistence/tree/3.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", + "type": "tidelift" + } + ], + "time": "2023-05-17T18:32:04+00:00" + }, + { + "name": "doctrine/sql-formatter", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", + "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4" + }, + "bin": [ + "bin/sql-formatter" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\SqlFormatter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "https://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/doctrine/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "support": { + "issues": "https://github.com/doctrine/sql-formatter/issues", + "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" + }, + "time": "2022-05-23T21:33:49+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/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/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "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.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "symfony/apache-pack", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/apache-pack.git", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/apache-pack/zipball/3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "shasum": "" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for Apache support in Symfony", + "support": { + "issues": "https://github.com/symfony/apache-pack/issues", + "source": "https://github.com/symfony/apache-pack/tree/master" + }, + "time": "2017-12-12T01:46:35+00:00" + }, + { + "name": "symfony/cache", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "378e30a864c868d635353f103a5a5e7569f029ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/378e30a864c868d635353f103a5a5e7569f029ec", + "reference": "378e30a864c868d635353f103a5a5e7569f029ec", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "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 extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v7.0.2" + }, + "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": "2023-12-29T15:37:40+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "1d74b127da04ffa87aa940abe15446fa89653778" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", + "reference": "1d74b127da04ffa87aa940abe15446fa89653778", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "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 caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v3.4.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": "2023-09-25T12:52:38+00:00" + }, + { + "name": "symfony/config", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/8789646600f4e7e451dde9e1dc81cfa429f3857a", + "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^6.4|^7.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "require-dev": { + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v7.0.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": "2023-11-09T08:30:23+00:00" + }, + { + "name": "symfony/console", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "f8587c4cdc5acad67af71c37db34ef03af91e59c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/f8587c4cdc5acad67af71c37db34ef03af91e59c", + "reference": "f8587c4cdc5acad67af71c37db34ef03af91e59c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.0.2" + }, + "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": "2023-12-10T16:54:46+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/bd25ef7c937b9da12510bdc4f1c66728f19620e3", + "reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^3.3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<6.4", + "symfony/finder": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "symfony/config": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v7.0.2" + }, + "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": "2023-12-28T19:18:20+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "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.4.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": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "5e8e95e8389d03f2f3ae16a6c7c804849ed483b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/5e8e95e8389d03f2f3ae16a6c7c804849ed483b5", + "reference": "5e8e95e8389d03f2f3ae16a6c7c804849ed483b5", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "^2", + "doctrine/persistence": "^3.1", + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "doctrine/lexer": "<1.1", + "doctrine/orm": "<2.15", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/form": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/lock": "<6.4", + "symfony/messenger": "<6.4", + "symfony/property-info": "<6.4", + "symfony/security-bundle": "<6.4", + "symfony/security-core": "<6.4", + "symfony/validator": "<6.4" + }, + "require-dev": { + "doctrine/collections": "^1.0|^2.0", + "doctrine/data-fixtures": "^1.1", + "doctrine/dbal": "^3.6|^4", + "doctrine/orm": "^2.15|^3", + "psr/log": "^1|^2|^3", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/doctrine-messenger": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "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 integration for Doctrine with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.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": "2023-11-17T16:04:05+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "1e3e123fd1887fb2097ad38205a9a866a52d4dcc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1e3e123fd1887fb2097ad38205a9a866a52d4dcc", + "reference": "1e3e123fd1887fb2097ad38205a9a866a52d4dcc", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "conflict": { + "symfony/console": "<6.4", + "symfony/process": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "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": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "source": "https://github.com/symfony/dotenv/tree/v7.0.2" + }, + "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": "2023-12-28T19:18:20+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/80b1258be1b84c12a345d0ec3881bbf2e5270cc2", + "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.0.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": "2023-10-20T16:35:23+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/098b62ae81fdd6cbf941f355059f617db28f4f9a", + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.2" + }, + "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": "2023-12-27T22:24:19+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "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.4.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": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7da8ea2362a283771478c5f7729cfcb43a76b8b7", + "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.0.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": "2023-07-27T06:33:22+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.0.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": "2023-10-31T17:59:56+00:00" + }, + { + "name": "symfony/flex", + "version": "v2.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.1", + "php": ">=8.0" + }, + "require-dev": { + "composer/composer": "^2.1", + "symfony/dotenv": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/phpunit-bridge": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "support": { + "issues": "https://github.com/symfony/flex/issues", + "source": "https://github.com/symfony/flex/tree/v2.4.3" + }, + "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-01-02T11:08:32+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "c647b0162e2190cbcd4a21174482af645e11367c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c647b0162e2190cbcd4a21174482af645e11367c", + "reference": "c647b0162e2190cbcd4a21174482af645e11367c", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.2", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^6.4|^7.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/asset": "<6.4", + "symfony/asset-mapper": "<6.4", + "symfony/clock": "<6.4", + "symfony/console": "<6.4", + "symfony/dom-crawler": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/lock": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/scheduler": "<6.4", + "symfony/security-core": "<6.4", + "symfony/security-csrf": "<6.4", + "symfony/serializer": "<6.4", + "symfony/stopwatch": "<6.4", + "symfony/translation": "<6.4", + "symfony/twig-bridge": "<6.4", + "symfony/twig-bundle": "<6.4", + "symfony/validator": "<6.4", + "symfony/web-profiler-bundle": "<6.4", + "symfony/workflow": "<6.4" + }, + "require-dev": { + "doctrine/persistence": "^1.3|^2|^3", + "dragonmantank/cron-expression": "^3.1", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "seld/jsonlint": "^1.10", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/dotenv": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/mailer": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/notifier": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/scheduler": "^6.4|^7.0", + "symfony/security-bundle": "^6.4|^7.0", + "symfony/semaphore": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "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 tight integration between Symfony components and the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/framework-bundle/tree/v7.0.2" + }, + "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": "2023-12-29T15:37:40+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "47d72323200934694def5d57083899d774a2b110" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/47d72323200934694def5d57083899d774a2b110", + "reference": "47d72323200934694def5d57083899d774a2b110", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.0.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": "2023-11-07T15:10:37+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "237d3008bc3f5db3e066e348dc0a6435d70a52bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/237d3008bc3f5db3e066e348dc0a6435d70a52bb", + "reference": "237d3008bc3f5db3e066e348dc0a6435d70a52bb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.0.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.0.2" + }, + "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": "2023-12-30T15:41:17+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "875e90aeea2777b6f135677f618529449334a612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/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.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/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.28.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": "2023-07-28T09:04:16+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "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 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/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.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.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": "2023-08-16T06:22:46+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "78866be67255f42716271e33d1d8b64eb6e47bd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/78866be67255f42716271e33d1d8b64eb6e47bd9", + "reference": "78866be67255f42716271e33d1d8b64eb6e47bd9", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.0.2" + }, + "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": "2023-12-29T15:37:40+00:00" + }, + { + "name": "symfony/runtime", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/runtime.git", + "reference": "65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/runtime/zipball/65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406", + "reference": "65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.2" + }, + "conflict": { + "symfony/dotenv": "<6.4" + }, + "require-dev": { + "composer/composer": "^2.6", + "symfony/console": "^6.4|^7.0", + "symfony/dotenv": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "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": "Enables decoupling PHP applications from global state", + "homepage": "https://symfony.com", + "keywords": [ + "runtime" + ], + "support": { + "source": "https://github.com/symfony/runtime/tree/v7.0.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": "2023-10-20T16:35:23+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "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.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-26T14:02:43+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a", + "reference": "7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { "psr-4": { - "FastRoute\\": "src/" + "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/v7.0.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": "2023-07-05T13:06:06+00:00" + }, + { + "name": "symfony/string", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/cc78f14f91f5e53b42044d0620961c48028ff9f5", + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { "files": [ - "src/functions.php" + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov", - "email": "nikic@php.net" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Fast request router for PHP", + "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": [ - "router", - "routing" + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.0.2" + }, + "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": "2023-12-10T16:54:46+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "5f6f1a527002068f6d40fda068399220eabebf71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5f6f1a527002068f6d40fda068399220eabebf71", + "reference": "5f6f1a527002068f6d40fda068399220eabebf71", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "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": { - "issues": "https://github.com/nikic/FastRoute/issues", - "source": "https://github.com/nikic/FastRoute/tree/master" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.2" }, - "time": "2018-02-13T20:26:39+00:00" + "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": "2023-12-28T19:18:20+00:00" }, { - "name": "opis/closure", - "version": "3.6.1", + "name": "symfony/var-exporter", + "version": "v7.0.2", "source": { "type": "git", - "url": "https://github.com/opis/closure.git", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5" + "url": "https://github.com/symfony/var-exporter.git", + "reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/345c62fefe92243c3a06fc0cc65f2ec1a47e0764", + "reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0" + "php": ">=8.2" }, "require-dev": { - "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.6.x-dev" + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.0.2" + }, + "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": "2023-12-27T08:42:13+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "0055b230c408428b9b5cde7c55659555be5c0278" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0055b230c408428b9b5cde7c55659555be5c0278", + "reference": "0055b230c408428b9b5cde7c55659555be5c0278", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", "autoload": { "psr-4": { - "Opis\\Closure\\": "src/" + "Symfony\\Component\\Yaml\\": "" }, - "files": [ - "functions.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -567,265 +4115,373 @@ ], "authors": [ { - "name": "Marius Sarca", - "email": "marius.sarca@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Sorin Sarca", - "email": "sarca_sorin@hotmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", - "homepage": "https://opis.io/closure", - "keywords": [ - "anonymous functions", - "closure", - "function", - "serializable", - "serialization", - "serialize" - ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/opis/closure/issues", - "source": "https://github.com/opis/closure/tree/3.6.1" + "source": "https://github.com/symfony/yaml/tree/v7.0.0" }, - "time": "2020-11-07T02:01:34+00:00" - }, + "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": "2023-11-07T10:26:03+00:00" + } + ], + "packages-dev": [ { - "name": "php-di/invoker", - "version": "2.3.0", + "name": "composer/pcre", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/PHP-DI/Invoker.git", - "reference": "992fec6c56f2d1ad1ad5fee28267867c85bfb8f9" + "url": "https://github.com/composer/pcre.git", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/992fec6c56f2d1ad1ad5fee28267867c85bfb8f9", - "reference": "992fec6c56f2d1ad1ad5fee28267867c85bfb8f9", + "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", "shasum": "" }, "require": { - "php": ">=7.3", - "psr/container": "~1.0" + "php": "^7.4 || ^8.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", - "mnapoli/hard-mode": "~0.3.0", - "phpunit/phpunit": "^9.0" + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "Invoker\\": "src/" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Generic and extensible callable invoker", - "homepage": "https://github.com/PHP-DI/Invoker", + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "callable", - "dependency", - "dependency-injection", - "injection", - "invoke", - "invoker" + "PCRE", + "preg", + "regex", + "regular expression" ], "support": { - "issues": "https://github.com/PHP-DI/Invoker/issues", - "source": "https://github.com/PHP-DI/Invoker/tree/2.3.0" + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.1" }, "funding": [ { - "url": "https://github.com/mnapoli", + "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": "2021-01-15T10:25:40+00:00" + "time": "2023-10-11T07:11:09+00:00" }, { - "name": "php-di/php-di", - "version": "6.3.0", + "name": "composer/semver", + "version": "3.4.0", "source": { "type": "git", - "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "955cacea6b0beaba07e8c11b8367f5b3d5abe89f" + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/955cacea6b0beaba07e8c11b8367f5b3d5abe89f", - "reference": "955cacea6b0beaba07e8c11b8367f5b3d5abe89f", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", "shasum": "" }, "require": { - "opis/closure": "^3.5.5", - "php": ">=7.2.0", - "php-di/invoker": "^2.0", - "php-di/phpdoc-reader": "^2.0.1", - "psr/container": "^1.0" - }, - "provide": { - "psr/container-implementation": "^1.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "doctrine/annotations": "~1.2", - "friendsofphp/php-cs-fixer": "^2.4", - "mnapoli/phpunit-easymock": "^1.2", - "ocramius/proxy-manager": "~2.0.2", - "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^8.5|^9.0" - }, - "suggest": { - "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)", - "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~2.0)" + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "DI\\": "src/" - }, - "files": [ - "src/functions.php" - ] + "Composer\\Semver\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "The dependency injection container for humans", - "homepage": "https://php-di.org/", + "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": [ - "PSR-11", - "container", - "container-interop", - "dependency injection", - "di", - "ioc", - "psr11" + "semantic", + "semver", + "validation", + "versioning" ], "support": { - "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/6.3.0" + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" }, "funding": [ { - "url": "https://github.com/mnapoli", + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", + "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], - "time": "2020-10-12T14:39:15+00:00" + "time": "2023-08-31T09:50:34+00:00" }, { - "name": "php-di/phpdoc-reader", - "version": "2.2.1", + "name": "composer/xdebug-handler", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/PHP-DI/PhpDocReader.git", - "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c" + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/66daff34cbd2627740ffec9469ffbac9f8c8185c", - "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", "shasum": "" }, "require": { - "php": ">=7.2.0" + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "mnapoli/hard-mode": "~0.3.0", - "phpunit/phpunit": "^8.5|^9.0" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" }, "type": "library", "autoload": { "psr-4": { - "PhpDocReader\\": "src/PhpDocReader" + "Composer\\XdebugHandler\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)", + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", "keywords": [ - "phpdoc", - "reflection" + "Xdebug", + "performance" ], "support": { - "issues": "https://github.com/PHP-DI/PhpDocReader/issues", - "source": "https://github.com/PHP-DI/PhpDocReader/tree/2.2.1" + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" }, - "time": "2020-10-12T12:39:22+00:00" + "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": "2022-02-25T21:32:43+00:00" }, { - "name": "php-di/slim-bridge", - "version": "3.1.0", + "name": "ergebnis/composer-normalize", + "version": "2.41.1", "source": { "type": "git", - "url": "https://github.com/PHP-DI/Slim-Bridge.git", - "reference": "c118174d07e5b6969f678298d6c44364acb2afd7" + "url": "https://github.com/ergebnis/composer-normalize.git", + "reference": "01eb2d9b8623828ec2264f54d7782a25558d27b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/Slim-Bridge/zipball/c118174d07e5b6969f678298d6c44364acb2afd7", - "reference": "c118174d07e5b6969f678298d6c44364acb2afd7", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/01eb2d9b8623828ec2264f54d7782a25558d27b2", + "reference": "01eb2d9b8623828ec2264f54d7782a25558d27b2", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0", - "php-di/invoker": "^2.0.0", - "php-di/php-di": "^6.0.0", - "slim/slim": "^4.2.0" + "composer-plugin-api": "^2.0.0", + "ergebnis/json": "^1.1.0", + "ergebnis/json-normalizer": "^4.4.1", + "ergebnis/json-printer": "^3.4.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12", + "localheinz/diff": "^1.1.1", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" }, "require-dev": { - "laminas/laminas-diactoros": "^2.1", - "phpunit/phpunit": ">= 7.0 < 10" + "composer/composer": "^2.6.6", + "ergebnis/license": "^2.4.0", + "ergebnis/php-cs-fixer-config": "~6.14.0", + "ergebnis/phpunit-slow-test-detector": "^2.7.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.9", + "phpunit/phpunit": "^10.5.3", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.12", + "roave/backward-compatibility-check": "^8.4.0", + "symfony/filesystem": "^6.4.0", + "vimeo/psalm": "^5.17.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + }, + "plugin-optional": true }, - "type": "library", "autoload": { "psr-4": { - "DI\\Bridge\\Slim\\": "src/" + "Ergebnis\\Composer\\Normalize\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PHP-DI integration in Slim", + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a composer plugin for normalizing composer.json.", + "homepage": "https://github.com/ergebnis/composer-normalize", + "keywords": [ + "composer", + "normalize", + "normalizer", + "plugin" + ], "support": { - "issues": "https://github.com/PHP-DI/Slim-Bridge/issues", - "source": "https://github.com/PHP-DI/Slim-Bridge/tree/3.1.0" + "issues": "https://github.com/ergebnis/composer-normalize/issues", + "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2020-12-02T16:09:06+00:00" + "time": "2023-12-14T09:37:52+00:00" }, { - "name": "psr/container", - "version": "1.1.1", + "name": "ergebnis/json", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "url": "https://github.com/ergebnis/json.git", + "reference": "9f2b9086c43b189d7044a5b6215a931fb6e9125d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/ergebnis/json/zipball/9f2b9086c43b189d7044a5b6215a931fb6e9125d", + "reference": "9f2b9086c43b189d7044a5b6215a931fb6e9125d", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.29.0", + "ergebnis/data-provider": "^3.0.0", + "ergebnis/license": "^2.2.0", + "ergebnis/php-cs-fixer-config": "^6.6.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.4", + "phpunit/phpunit": "^10.4.1", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.5", + "vimeo/psalm": "^5.15.0" }, "type": "library", + "extra": { + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Ergebnis\\Json\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -834,52 +4490,69 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Provides a Json value object for representing a valid JSON string.", + "homepage": "https://github.com/ergebnis/json", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "json" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "issues": "https://github.com/ergebnis/json/issues", + "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2023-10-10T07:57:48+00:00" }, { - "name": "psr/http-factory", - "version": "1.0.1", + "name": "ergebnis/json-normalizer", + "version": "4.4.1", "source": { "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "url": "https://github.com/ergebnis/json-normalizer.git", + "reference": "d28f36af9763ee6bc4e2a2390c0348963df7881b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/d28f36af9763ee6bc4e2a2390c0348963df7881b", + "reference": "d28f36af9763ee6bc4e2a2390c0348963df7881b", "shasum": "" }, "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0" + "ergebnis/json": "^1.1.0", + "ergebnis/json-pointer": "^3.2.0", + "ergebnis/json-printer": "^3.4.0", + "ergebnis/json-schema-validator": "^4.1.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "composer/semver": "^3.4.0", + "ergebnis/data-provider": "^3.2.0", + "ergebnis/license": "^2.4.0", + "ergebnis/php-cs-fixer-config": "~6.14.0", + "ergebnis/phpunit-slow-test-detector": "^2.7.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.9", + "phpunit/phpunit": "^10.5.3", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.12", + "roave/backward-compatibility-check": "^8.4.0", + "symfony/filesystem": "^6.4.0", + "symfony/finder": "^6.4.0", + "vimeo/psalm": "^5.17.0" }, + "suggest": { + "composer/semver": "If you want to use ComposerJsonNormalizer or VersionConstraintNormalizer" + }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Ergebnis\\Json\\Normalizer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -888,52 +4561,64 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "Provides generic and vendor-specific normalizers for normalizing JSON documents.", + "homepage": "https://github.com/ergebnis/json-normalizer", "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" + "json", + "normalizer" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "issues": "https://github.com/ergebnis/json-normalizer/issues", + "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-normalizer" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2023-12-14T09:30:24+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "ergebnis/json-pointer", + "version": "3.3.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/ergebnis/json-pointer.git", + "reference": "8e517faefc06b7c761eaa041febef51a9375819a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/8e517faefc06b7c761eaa041febef51a9375819a", + "reference": "8e517faefc06b7c761eaa041febef51a9375819a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.29.0", + "ergebnis/data-provider": "^3.0.0", + "ergebnis/license": "^2.2.0", + "ergebnis/php-cs-fixer-config": "~6.7.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.4", + "phpunit/phpunit": "^10.4.1", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.5", + "vimeo/psalm": "^5.15.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Ergebnis\\Json\\Pointer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -942,52 +4627,59 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Provides JSON pointer as a value object.", + "homepage": "https://github.com/ergebnis/json-pointer", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "RFC6901", + "json", + "pointer" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "issues": "https://github.com/ergebnis/json-pointer/issues", + "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-pointer" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-10-10T14:41:06+00:00" }, { - "name": "psr/http-server-handler", - "version": "1.0.1", + "name": "ergebnis/json-printer", + "version": "3.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-server-handler.git", - "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7" + "url": "https://github.com/ergebnis/json-printer.git", + "reference": "05841593d72499de4f7ce4034a237c77e470558f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7", - "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/05841593d72499de4f7ce4034a237c77e470558f", + "reference": "05841593d72499de4f7ce4034a237c77e470558f", "shasum": "" }, "require": { - "php": ">=7.0", - "psr/http-message": "^1.0" + "ext-json": "*", + "ext-mbstring": "*", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "ergebnis/license": "^2.2.0", + "ergebnis/php-cs-fixer-config": "^6.6.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.3", + "phpunit/phpunit": "^10.4.1", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.5", + "vimeo/psalm": "^5.15.0" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Http\\Server\\": "src/" + "Ergebnis\\Json\\Printer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -996,56 +4688,69 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common interface for HTTP server-side request handler", + "description": "Provides a JSON printer, allowing for flexible indentation.", + "homepage": "https://github.com/ergebnis/json-printer", "keywords": [ - "handler", - "http", - "http-interop", - "psr", - "psr-15", - "psr-7", - "request", - "response", - "server" + "formatter", + "json", + "printer" ], "support": { - "issues": "https://github.com/php-fig/http-server-handler/issues", - "source": "https://github.com/php-fig/http-server-handler/tree/master" + "issues": "https://github.com/ergebnis/json-printer/issues", + "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-printer" }, - "time": "2018-10-30T16:46:14+00:00" + "time": "2023-10-10T07:42:48+00:00" }, { - "name": "psr/http-server-middleware", - "version": "1.0.1", + "name": "ergebnis/json-schema-validator", + "version": "4.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-server-middleware.git", - "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5" + "url": "https://github.com/ergebnis/json-schema-validator.git", + "reference": "d568ed85d1cdc2e49d650c2fc234dc2516f3f25b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/2296f45510945530b9dceb8bcedb5cb84d40c5f5", - "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/d568ed85d1cdc2e49d650c2fc234dc2516f3f25b", + "reference": "d568ed85d1cdc2e49d650c2fc234dc2516f3f25b", "shasum": "" }, "require": { - "php": ">=7.0", - "psr/http-message": "^1.0", - "psr/http-server-handler": "^1.0" + "ergebnis/json": "^1.0.1", + "ergebnis/json-pointer": "^3.2.0", + "ext-json": "*", + "justinrainbow/json-schema": "^5.2.12", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.21.0", + "ergebnis/data-provider": "^3.0.0", + "ergebnis/license": "^2.2.0", + "ergebnis/php-cs-fixer-config": "~6.6.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "fakerphp/faker": "^1.23.0", + "infection/infection": "~0.27.4", + "phpunit/phpunit": "^10.4.1", + "psalm/plugin-phpunit": "~0.18.4", + "rector/rector": "~0.18.5", + "vimeo/psalm": "^5.15.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" } }, "autoload": { "psr-4": { - "Psr\\Http\\Server\\": "src/" + "Ergebnis\\Json\\SchemaValidator\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1054,53 +4759,81 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" } ], - "description": "Common interface for HTTP server-side middleware", + "description": "Provides a JSON schema validator, building on top of justinrainbow/json-schema.", + "homepage": "https://github.com/ergebnis/json-schema-validator", "keywords": [ - "http", - "http-interop", - "middleware", - "psr", - "psr-15", - "psr-7", - "request", - "response" + "json", + "schema", + "validator" ], "support": { - "issues": "https://github.com/php-fig/http-server-middleware/issues", - "source": "https://github.com/php-fig/http-server-middleware/tree/master" + "issues": "https://github.com/ergebnis/json-schema-validator/issues", + "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/json-schema-validator" }, - "time": "2018-10-30T17:12:04+00:00" + "time": "2023-10-10T14:16:57+00:00" }, { - "name": "psr/log", - "version": "1.1.3", + "name": "friendsofphp/php-cs-fixer", + "version": "v3.46.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/be6831c9af1740470d2a773119b9273f8ac1c3d2", + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2", "shasum": "" }, "require": { - "php": ">=5.3.0" + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0 || ^5.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.0", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", + "phpunit/phpunit": "^9.6 || ^10.5.5", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "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": { - "Psr\\Log\\": "Psr/Log/" + "PhpCsFixer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1109,48 +4842,67 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "A tool to automatically fix PHP code style", "keywords": [ - "log", - "psr", - "psr-3" + "Static code analysis", + "fixer", + "standards", + "static analysis" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.46.0" }, - "time": "2020-03-23T09:12:05+00:00" + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2024-01-03T21:38:46+00:00" }, { - "name": "psr/simple-cache", - "version": "1.0.1", + "name": "justinrainbow/json-schema", + "version": "v5.2.13", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" }, + "bin": [ + "bin/validate-json" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" + "JsonSchema\\": "src/JsonSchema/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1159,103 +4911,124 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" } ], - "description": "Common interfaces for simple caching", + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" + "json", + "schema" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/v5.2.13" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2023-09-26T02:20:38+00:00" }, { - "name": "ralouphie/getallheaders", - "version": "3.0.3", + "name": "localheinz/diff", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" + "url": "https://github.com/localheinz/diff.git", + "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", + "url": "https://api.github.com/repos/localheinz/diff/zipball/851bb20ea8358c86f677f5f111c4ab031b1c764c", + "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^7.1 || ^8.0" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "autoload": { - "files": [ - "src/getallheaders.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "A polyfill for getallheaders.", + "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", + "homepage": "https://github.com/localheinz/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" + "source": "https://github.com/localheinz/diff/tree/main" }, - "time": "2019-03-08T08:55:37+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-07-06T04:49:32+00:00" }, { - "name": "slim/psr7", - "version": "0.6", + "name": "masterminds/html5", + "version": "2.8.1", "source": { "type": "git", - "url": "https://github.com/slimphp/Slim-Psr7.git", - "reference": "23015a8814382c244315602d44cb02d412b6b059" + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/23015a8814382c244315602d44cb02d412b6b059", - "reference": "23015a8814382c244315602d44cb02d412b6b059", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", "shasum": "" }, "require": { - "fig/http-message-util": "^1.1.2", - "php": "^7.1", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "ralouphie/getallheaders": "^3" - }, - "provide": { - "psr/http-message-implementation": "1.0" + "ext-dom": "*", + "php": ">=5.3.0" }, "require-dev": { - "ext-json": "*", - "http-interop/http-factory-tests": "^0.6.0", - "php-http/psr7-integration-tests": "dev-master", - "phpstan/phpstan": "^0.10", - "phpunit/phpunit": "^6.0|^7.0", - "squizlabs/php_codesniffer": "^3.3" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, "autoload": { "psr-4": { - "Slim\\Psr7\\": "src" + "Masterminds\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1264,930 +5037,705 @@ ], "authors": [ { - "name": "Josh Lockhart", - "email": "hello@joshlockhart.com", - "homepage": "http://joshlockhart.com" - }, - { - "name": "Andrew Smith", - "email": "a.smith@silentworks.co.uk", - "homepage": "http://silentworks.co.uk" + "name": "Matt Butcher", + "email": "technosophos@gmail.com" }, { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" + "name": "Matt Farina", + "email": "matt@mattfarina.com" }, { - "name": "Pierre Berube", - "email": "pierre@lgse.com", - "homepage": "http://www.lgse.com" + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" } ], - "description": "Strict PSR-7 implementation", - "homepage": "https://www.slimframework.com", + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", "keywords": [ - "http", - "psr-7", - "psr7" + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" ], "support": { - "issues": "https://github.com/slimphp/Slim-Psr7/issues", - "source": "https://github.com/slimphp/Slim-Psr7/tree/master" + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" }, - "time": "2019-10-05T20:27:07+00:00" + "time": "2023-05-10T11:58:31+00:00" }, { - "name": "slim/slim", - "version": "4.7.1", + "name": "myclabs/deep-copy", + "version": "1.11.1", "source": { "type": "git", - "url": "https://github.com/slimphp/Slim.git", - "reference": "0905e0775f8c1cfb3bbcfabeb6588dcfd8b82d3f" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/0905e0775f8c1cfb3bbcfabeb6588dcfd8b82d3f", - "reference": "0905e0775f8c1cfb3bbcfabeb6588dcfd8b82d3f", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { - "ext-json": "*", - "nikic/fast-route": "^1.3", - "php": "^7.2 || ^8.0", - "psr/container": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "psr/http-server-handler": "^1.0", - "psr/http-server-middleware": "^1.0", - "psr/log": "^1.1" - }, - "require-dev": { - "adriansuter/php-autoload-override": "^1.2", - "ext-simplexml": "*", - "guzzlehttp/psr7": "^1.7", - "http-interop/http-factory-guzzle": "^1.0", - "laminas/laminas-diactoros": "^2.4", - "nyholm/psr7": "^1.3", - "nyholm/psr7-server": "^1.0.1", - "phpspec/prophecy": "^1.12", - "phpstan/phpstan": "^0.12.58", - "phpunit/phpunit": "^8.5.13", - "slim/http": "^1.2", - "slim/psr7": "^1.3", - "squizlabs/php_codesniffer": "^3.5", - "weirdan/prophecy-shim": "^1.0 || ^2.0.2" + "php": "^7.1 || ^8.0" }, - "suggest": { - "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", - "ext-xml": "Needed to support XML format in BodyParsingMiddleware", - "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", - "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." + "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", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "Slim\\": "Slim" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Josh Lockhart", - "email": "hello@joshlockhart.com", - "homepage": "https://joshlockhart.com" - }, - { - "name": "Andrew Smith", - "email": "a.smith@silentworks.co.uk", - "homepage": "http://silentworks.co.uk" - }, - { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" - }, - { - "name": "Pierre Berube", - "email": "pierre@lgse.com", - "homepage": "http://www.lgse.com" - }, - { - "name": "Gabriel Manricks", - "email": "gmanricks@me.com", - "homepage": "http://gabrielmanricks.com" - } - ], - "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", - "homepage": "https://www.slimframework.com", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "api", - "framework", - "micro", - "router" + "clone", + "copy", + "duplicate", + "object", + "object graph" ], "support": { - "docs": "https://www.slimframework.com/docs/v4/", - "forum": "https://discourse.slimframework.com/", - "irc": "irc://irc.freenode.net:6667/slimphp", - "issues": "https://github.com/slimphp/Slim/issues", - "rss": "https://www.slimframework.com/blog/feed.rss", - "slack": "https://slimphp.slack.com/", - "source": "https://github.com/slimphp/Slim", - "wiki": "https://github.com/slimphp/Slim/wiki" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { - "url": "https://opencollective.com/slimphp", - "type": "open_collective" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-12-01T19:41:22+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.22.1", + "name": "nikic/php-parser", + "version": "v4.18.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-tokenizer": "*", + "php": ">=7.0" }, - "suggest": { - "ext-mbstring": "For best performance" + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "4.9-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] + "PhpParser\\": "lib/PhpParser" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Nikita Popov" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", + "description": "A PHP parser written in PHP", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "parser", + "php" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.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": "2021-01-22T09:19:47+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.22.1", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "files": [ - "bootstrap.php" - ], "classmap": [ - "Resources/stubs" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "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": "2021-01-07T16:49:33+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { - "name": "symfony/translation", - "version": "v5.2.6", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "2cc7f45d96db9adfcf89adf4401d9dfed509f4e1" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/2cc7f45d96db9adfcf89adf4401d9dfed509f4e1", - "reference": "2cc7f45d96db9adfcf89adf4401d9dfed509f4e1", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.15", - "symfony/translation-contracts": "^2.3" - }, - "conflict": { - "symfony/config": "<4.4", - "symfony/dependency-injection": "<5.0", - "symfony/http-kernel": "<5.0", - "symfony/twig-bundle": "<5.0", - "symfony/yaml": "<4.4" - }, - "provide": { - "symfony/translation-implementation": "2.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/dependency-injection": "^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/http-kernel": "^5.0", - "symfony/intl": "^4.4|^5.0", - "symfony/service-contracts": "^1.1.2|^2", - "symfony/yaml": "^4.4|^5.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to internationalize your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/translation/tree/v5.2.6" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "url": "https://github.com/fabpot", - "type": "github" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "time": "2021-03-23T19:33:48+00:00" + "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": "symfony/translation-contracts", - "version": "v2.4.0", + "name": "phpstan/phpstan", + "version": "1.10.55", "source": { "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "95c812666f3e91db75385749fe219c5e494c7f95" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95", - "reference": "95c812666f3e91db75385749fe219c5e494c7f95", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9a88f9d18ddf4cf54c922fbeac16c4cb164c5949", + "reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": "^7.2|^8.0" }, - "suggest": { - "symfony/translation-implementation": "" + "conflict": { + "phpstan/phpstan-shim": "*" }, + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, "autoload": { - "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - } + "files": [ + "bootstrap.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": "Generic abstractions related to translation", - "homepage": "https://symfony.com", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "dev", + "static analysis" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0" + "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://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/ondrejmirtes", + "type": "github" }, { - "url": "https://github.com/fabpot", + "url": "https://github.com/phpstan", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", "type": "tidelift" } ], - "time": "2021-03-23T23:28:01+00:00" - } - ], - "packages-dev": [ + "time": "2024-01-08T12:32:40+00:00" + }, { - "name": "composer/semver", - "version": "3.2.5", + "name": "phpunit/php-code-coverage", + "version": "10.1.11", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "78c3b7625965c2513ee96569a4dbb62601784145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9", - "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145", + "reference": "78c3b7625965c2513ee96569a4dbb62601784145", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpunit/phpunit": "^10.1" + }, + "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": "3.x-dev" + "dev-main": "10.1-dev" } }, "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "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" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "coverage", + "testing", + "xunit" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.5" + "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/10.1.11" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2021-05-24T12:41:47+00:00" + "time": "2023-12-21T15:38:30+00:00" }, { - "name": "composer/xdebug-handler", - "version": "2.0.1", + "name": "phpunit/php-file-iterator", + "version": "4.1.0", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", - "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1.0" + "php": ">=8.1" }, "require-dev": { - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpunit/phpunit": "^10.0" }, "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Restarts a process without Xdebug.", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ - "Xdebug", - "performance" + "filesystem", + "iterator" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.1" + "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/4.1.0" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2021-05-05T19:37:51+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { - "name": "doctrine/annotations", - "version": "1.13.1", + "name": "phpunit/php-invoker", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", - "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" + "php": ">=8.1" }, "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2" + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "annotations", - "docblock", - "parser" + "process" ], "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.1" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, - "time": "2021-05-16T18:07:53+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" }, { - "name": "doctrine/lexer", - "version": "1.2.1", + "name": "phpunit/php-text-template", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=8.1" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^8.2" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" + "template" ], "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.1" + "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/3.0.1" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "time": "2020-05-25T17:44:05+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v2.19.0", + "name": "phpunit/php-timer", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "d5b8a9d852b292c2f8a035200fa6844b1f82300b" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/d5b8a9d852b292c2f8a035200fa6844b1f82300b", - "reference": "d5b8a9d852b292c2f8a035200fa6844b1f82300b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.2 || ^2.0", - "doctrine/annotations": "^1.2", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", - "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0", - "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0 || ^5.0", - "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.4", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4.2", - "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", - "symfony/phpunit-bridge": "^5.2.1", - "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + "php": ">=8.1" }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters.", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", + "type": "library", "extra": { "branch-alias": { - "dev-master": "2.19-dev" + "dev-main": "6.0-dev" } }, "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/Test/IsIdenticalConstraint.php", - "tests/Test/TokensWithObservedTransformers.php", - "tests/TestCase.php" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A tool to automatically fix PHP code style", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.0" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { - "url": "https://github.com/keradus", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2021-05-03T21:43:24+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.10.5", + "name": "phpunit/phpunit", + "version": "10.5.5", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ - "bin/php-parse" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-main": "10.5-dev" } }, "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2195,42 +5743,65 @@ ], "authors": [ { - "name": "Nikita Popov" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A PHP parser written in PHP", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "parser", - "php" + "phpunit", + "testing", + "xunit" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.5" }, - "time": "2021-05-03T19:11:20+00:00" + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-12-27T15:13:52+00:00" }, { - "name": "php-cs-fixer/diff", - "version": "v1.3.1", + "name": "sebastian/cli-parser", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0 || ^8.0" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2242,974 +5813,915 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "SpacePossum" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "sebastian/diff v2 backport support for PHP5.6", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" }, - "time": "2020-10-14T08:39:05+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" }, { - "name": "phpstan/phpstan", - "version": "0.12.88", + "name": "sebastian/code-unit", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/464d1a81af49409c41074aa6640ed0c4cbd9bb68", - "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": ">=8.1" }, - "conflict": { - "phpstan/phpstan-shim": "*" + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "0.12-dev" + "dev-main": "2.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "PHPStan - PHP Static Analysis Tool", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.88" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { - "url": "https://github.com/ondrejmirtes", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2021-05-17T12:24:49+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { - "name": "prestashop/header-stamp", - "version": "v2.0", + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/PrestaShopCorp/header-stamp.git", - "reference": "db3d7d4604e6ef2ac9cf5d88b66601b96d2b9977" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/header-stamp/zipball/db3d7d4604e6ef2ac9cf5d88b66601b96d2b9977", - "reference": "db3d7d4604e6ef2ac9cf5d88b66601b96d2b9977", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "nikic/php-parser": "^4.10", - "php": ">=7.2.5", - "symfony/console": "^3.4 || ~4.0 || ~5.0", - "symfony/finder": "^3.4 || ~4.0 || ~5.0" + "php": ">=8.1" }, "require-dev": { - "phpstan/phpstan": "^0.12.83", - "prestashop/php-dev-tools": "1.*" + "phpunit/phpunit": "^10.0" }, - "bin": [ - "bin/header-stamp" - ], "type": "library", - "autoload": { - "psr-4": { - "PrestaShop\\HeaderStamp\\": "src/" + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "AFL-3.0" + "BSD-3-Clause" ], "authors": [ { - "name": "PrestaShop SA", - "email": "contact@prestashop.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Rewrite your file headers to add the license or to make them up-to-date", - "homepage": "https://github.com/PrestaShopCorp/header-stamp", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/PrestaShopCorp/header-stamp/issues", - "source": "https://github.com/PrestaShopCorp/header-stamp/tree/v2.0" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, - "time": "2021-04-16T13:04:37+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" }, { - "name": "prestashop/php-dev-tools", - "version": "v4.0.1", + "name": "sebastian/comparator", + "version": "5.0.1", "source": { "type": "git", - "url": "https://github.com/PrestaShop/php-dev-tools.git", - "reference": "f675c0c296b8399cdd99ac9c09f414ae4a2e72b2" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/f675c0c296b8399cdd99ac9c09f414ae4a2e72b2", - "reference": "f675c0c296b8399cdd99ac9c09f414ae4a2e72b2", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^2.14", - "php": ">=7.2.5", - "prestashop/header-stamp": "^2.0", - "squizlabs/php_codesniffer": "^3.4", - "symfony/console": "~3.2 || ~4.0 || ~5.0", - "symfony/filesystem": "~3.2 || ~4.0 || ~5.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, - "conflict": { - "friendsofphp/php-cs-fixer": "2.18.3" + "require-dev": { + "phpunit/phpunit": "^10.3" }, - "bin": [ - "bin/prestashop-coding-standards" - ], "type": "library", - "autoload": { - "psr-4": { - "PrestaShop\\CodingStandards\\": "src/" + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "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" ], - "description": "PrestaShop coding standards", "support": { - "issues": "https://github.com/PrestaShop/php-dev-tools/issues", - "source": "https://github.com/PrestaShop/php-dev-tools/tree/v4.0.1" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" }, - "time": "2021-05-10T09:33:33+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-14T13:18:12+00:00" }, { - "name": "psr/cache", - "version": "1.0.1", + "name": "sebastian/complexity", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { - "php": ">=5.3.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "3.2-dev" } }, "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "source": "https://github.com/php-fig/cache/tree/master" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, - "time": "2016-08-06T20:24:11+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:37:17+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "sebastian/diff", + "version": "5.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f", + "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "5.1-dev" } }, "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Standard interfaces for event handling.", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "events", - "psr", - "psr-14" + "diff", + "udiff", + "unidiff", + "unified diff" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0" }, - "time": "2019-01-08T18:20:26+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T10:55:06+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.6.0", + "name": "sebastian/environment", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-main": "6.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ - "phpcs", - "standards" + "Xdebug", + "environment", + "hhvm" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" }, - "time": "2021-04-09T00:54:41+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-11T05:39:26+00:00" }, { - "name": "symfony/console", - "version": "v5.2.8", + "name": "sebastian/exporter", + "version": "5.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/polyfill-php80": "^1.15", - "symfony/service-contracts": "^1.1|^2", - "symfony/string": "^5.1" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "cli", - "command line", - "console", - "terminal" + "export", + "exporter" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.8" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-05-11T15:45:21+00:00" + "time": "2023-09-24T13:22:09+00:00" }, { - "name": "symfony/deprecation-contracts", - "version": "v2.4.0", + "name": "sebastian/global-state", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", - "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-main": "6.0-dev" } }, "autoload": { - "files": [ - "function.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-03-23T23:28:01+00:00" + "time": "2023-07-19T07:19:23+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v5.2.4", + "name": "sebastian/lines-of-code", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d08d6ec121a425897951900ab692b612a61d6240" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d08d6ec121a425897951900ab692b612a61d6240", - "reference": "d08d6ec121a425897951900ab692b612a61d6240", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/event-dispatcher-contracts": "^2", - "symfony/polyfill-php80": "^1.15" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/error-handler": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^4.4|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.4" + "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/2.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-02-18T17:12:37+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.4.0", + "name": "sebastian/object-enumerator", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11", - "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-main": "5.0-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-03-23T23:28:01+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { - "name": "symfony/filesystem", - "version": "v5.2.7", + "name": "sebastian/object-reflector", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/056e92acc21d977c37e6ea8e97374b2a6c8551b0", - "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.7" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-04-01T10:42:13+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { - "name": "symfony/finder", - "version": "v5.2.9", + "name": "sebastian/recursion-context", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", - "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.9" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-05-16T13:07:46+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { - "name": "symfony/options-resolver", - "version": "v5.2.4", + "name": "sebastian/type", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.15" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.2.4" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-27T12:56:27+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.22.1", + "name": "sebastian/version", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-main": "4.0-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.22.1", + "name": "symfony/browser-kit", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170" + "url": "https://github.com/symfony/browser-kit.git", + "reference": "c53a6e9bcb4528be535d458450b07aa81620459e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c53a6e9bcb4528be535d458450b07aa81620459e", + "reference": "c53a6e9bcb4528be535d458450b07aa81620459e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2", + "symfony/dom-crawler": "^6.4|^7.0" }, - "suggest": { - "ext-intl": "For best performance" + "require-dev": { + "symfony/css-selector": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + "Symfony\\Component\\BrowserKit\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3218,26 +6730,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's grapheme_* functions", + "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + "source": "https://github.com/symfony/browser-kit/tree/v7.0.0" }, "funding": [ { @@ -3253,47 +6757,32 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2023-10-31T17:37:24+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.22.1", + "name": "symfony/css-selector", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + "url": "https://github.com/symfony/css-selector.git", + "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/bb51d46e53ef8d50d523f0c5faedba056a27943e", + "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" + "php": ">=8.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + "Symfony\\Component\\CssSelector\\": "" }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3302,26 +6791,22 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "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": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + "source": "https://github.com/symfony/css-selector/tree/v7.0.0" }, "funding": [ { @@ -3337,34 +6822,39 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2023-10-31T17:59:56+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", + "name": "symfony/dom-crawler", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "d13205f444a535f4a6e52186aedbc99664f66a86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d13205f444a535f4a6e52186aedbc99664f66a86", + "reference": "d13205f444a535f4a6e52186aedbc99664f66a86", "shasum": "" }, "require": { - "php": ">=7.1" + "masterminds/html5": "^2.6", + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" }, - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" + "require-dev": { + "symfony/css-selector": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3372,24 +6862,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" + "source": "https://github.com/symfony/dom-crawler/tree/v7.0.0" }, "funding": [ { @@ -3405,67 +6889,83 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2023-11-20T16:43:42+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.22.1", + "name": "symfony/maker-bundle", + "version": "v1.52.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + "url": "https://github.com/symfony/maker-bundle.git", + "reference": "112f9466c94a46ca33dc441eee59a12cd1790757" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/112f9466c94a46ca33dc441eee59a12cd1790757", + "reference": "112f9466c94a46ca33dc441eee59a12cd1790757", "shasum": "" }, "require": { - "php": ">=7.1" + "doctrine/inflector": "^2.0", + "nikic/php-parser": "^4.11", + "php": ">=8.1", + "symfony/config": "^6.3|^7.0", + "symfony/console": "^6.3|^7.0", + "symfony/dependency-injection": "^6.3|^7.0", + "symfony/deprecation-contracts": "^2.2|^3", + "symfony/filesystem": "^6.3|^7.0", + "symfony/finder": "^6.3|^7.0", + "symfony/framework-bundle": "^6.3|^7.0", + "symfony/http-kernel": "^6.3|^7.0", + "symfony/process": "^6.3|^7.0" }, - "type": "library", + "conflict": { + "doctrine/doctrine-bundle": "<2.4", + "doctrine/orm": "<2.10" + }, + "require-dev": { + "composer/semver": "^3.0", + "doctrine/doctrine-bundle": "^2.5.0", + "doctrine/orm": "^2.10.0", + "symfony/http-client": "^6.3|^7.0", + "symfony/phpunit-bridge": "^6.3|^7.0", + "symfony/security-core": "^6.3|^7.0", + "symfony/yaml": "^6.3|^7.0", + "twig/twig": "^2.0|^3.0" + }, + "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] + "Symfony\\Bundle\\MakerBundle\\": "src/" + } }, "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 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", + "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", + "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "code generator", + "dev", + "generator", + "scaffold", + "scaffolding" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1" + "issues": "https://github.com/symfony/maker-bundle/issues", + "source": "https://github.com/symfony/maker-bundle/tree/v1.52.0" }, "funding": [ { @@ -3481,44 +6981,33 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2023-10-31T18:23:49+00:00" }, { - "name": "symfony/polyfill-php73", - "version": "v1.22.1", + "name": "symfony/options-resolver", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "url": "https://github.com/symfony/options-resolver.git", + "reference": "700ff4096e346f54cb628ea650767c8130f1001f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f", + "reference": "700ff4096e346f54cb628ea650767c8130f1001f", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Component\\OptionsResolver\\": "" }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3527,24 +7016,23 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Provides an improved replacement for the array_replace PHP function", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "config", + "configuration", + "options" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + "source": "https://github.com/symfony/options-resolver/tree/v7.0.0" }, "funding": [ { @@ -3560,30 +7048,49 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2023-08-08T10:20:21+00:00" }, { - "name": "symfony/process", - "version": "v5.2.7", + "name": "symfony/phpunit-bridge", + "version": "v7.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e" + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "92df075808c9437beca9540e25ae0c40eea1c061" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", - "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/92df075808c9437beca9540e25ae0c40eea1c061", + "reference": "92df075808c9437beca9540e25ae0c40eea1c061", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.15" + "php": ">=7.2.5" + }, + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.4|^7.0", + "symfony/polyfill-php81": "^1.27" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } }, - "type": "library", "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Bridge\\PhpUnit\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3595,18 +7102,18 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Executes commands in sub-processes", + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.3.0-BETA1" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.2" }, "funding": [ { @@ -3622,43 +7129,45 @@ "type": "tidelift" } ], - "time": "2021-04-08T10:27:02+00:00" + "time": "2023-12-19T11:23:03+00:00" }, { - "name": "symfony/service-contracts", - "version": "v2.4.0", + "name": "symfony/polyfill-php81", + "version": "v1.28.0", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", - "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1" - }, - "suggest": { - "symfony/service-implementation": "" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "1.28-dev" }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3674,18 +7183,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -3701,30 +7208,29 @@ "type": "tidelift" } ], - "time": "2021-04-01T10:43:52+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { - "name": "symfony/stopwatch", - "version": "v5.2.7", + "name": "symfony/process", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "d99310c33e833def36419c284f60e8027d359678" + "url": "https://github.com/symfony/process.git", + "reference": "13bdb1670c7f510494e04fcb2bfa29af63db9c0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d99310c33e833def36419c284f60e8027d359678", - "reference": "d99310c33e833def36419c284f60e8027d359678", + "url": "https://api.github.com/repos/symfony/process/zipball/13bdb1670c7f510494e04fcb2bfa29af63db9c0d", + "reference": "13bdb1670c7f510494e04fcb2bfa29af63db9c0d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1.0|^2" + "php": ">=8.2" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" + "Symfony\\Component\\Process\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3744,10 +7250,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a way to profile code", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.3.0-BETA1" + "source": "https://github.com/symfony/process/tree/v7.0.0" }, "funding": [ { @@ -3763,102 +7269,69 @@ "type": "tidelift" } ], - "time": "2021-03-29T15:28:41+00:00" + "time": "2023-11-20T16:43:42+00:00" }, { - "name": "symfony/string", - "version": "v5.2.8", + "name": "theseer/tokenizer", + "version": "1.2.2", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "files": [ - "Resources/functions.php" - ], - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { - "source": "https://github.com/symfony/string/tree/v5.2.8" + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/theseer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-05-10T14:56:10+00:00" + "time": "2023-11-20T00:12:19+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], - "prefer-stable": false, + "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=7.1", - "ext-json": "*", - "ext-simplexml": "*" + "php": ">=8.2", + "ext-ctype": "*", + "ext-iconv": "*" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.3.0" } diff --git a/config/bundles.php b/config/bundles.php new file mode 100644 index 0000000..de8898b --- /dev/null +++ b/config/bundles.php @@ -0,0 +1,8 @@ + ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], +]; diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml new file mode 100644 index 0000000..6899b72 --- /dev/null +++ b/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml new file mode 100644 index 0000000..3511e3d --- /dev/null +++ b/config/packages/doctrine.yaml @@ -0,0 +1,50 @@ +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + #server_version: '15' + + profiling_collect_backtrace: '%kernel.debug%' + orm: + auto_generate_proxy_classes: true + enable_lazy_ghost_objects: true + report_fields_where_declared: true + validate_xml_mapping: true + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + auto_mapping: true + dql: + datetime_functions: + date: DoctrineExtensions\Query\Mysql\Date + mappings: + App: + type: attribute + is_bundle: false + dir: '%kernel.project_dir%/src/Entity' + prefix: 'App\Entity' + alias: App + +when@test: + doctrine: + dbal: + +when@prod: + doctrine: + orm: + auto_generate_proxy_classes: false + proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' + query_cache_driver: + type: pool + pool: doctrine.system_cache_pool + result_cache_driver: + type: pool + pool: doctrine.result_cache_pool + + framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml new file mode 100644 index 0000000..29231d9 --- /dev/null +++ b/config/packages/doctrine_migrations.yaml @@ -0,0 +1,6 @@ +doctrine_migrations: + migrations_paths: + # namespace is arbitrary but should be different from App\Migrations + # as migrations classes should NOT be autoloaded + 'DoctrineMigrations': '%kernel.project_dir%/migrations' + enable_profiler: false diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml new file mode 100644 index 0000000..355bd4c --- /dev/null +++ b/config/packages/framework.yaml @@ -0,0 +1,23 @@ +# see https://symfony.com/doc/current/reference/configuration/framework.html +framework: + secret: '%env(APP_SECRET)%' + #csrf_protection: true + handle_all_throwables: true + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: null + cookie_secure: auto + cookie_samesite: lax + + #esi: true + #fragments: true + php_errors: + log: true + +when@test: + framework: + test: true + session: + storage_factory_id: session.storage.factory.mock_file diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml new file mode 100644 index 0000000..4b766ce --- /dev/null +++ b/config/packages/routing.yaml @@ -0,0 +1,12 @@ +framework: + router: + utf8: true + + # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. + # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands + #default_uri: http://localhost + +when@prod: + framework: + router: + strict_requirements: null diff --git a/config/preload.php b/config/preload.php new file mode 100644 index 0000000..5ebcdb2 --- /dev/null +++ b/config/preload.php @@ -0,0 +1,5 @@ + + + + + + + + + + + + + + + + tests + + + diff --git a/public/.htaccess b/public/.htaccess index 749bbf6..f7345df 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,7 +1,70 @@ +# Use the front controller as index file. It serves as a fallback solution when +# every other rewrite/redirect fails (e.g. in an aliased environment without +# mod_rewrite). Additionally, this reduces the matching process for the +# start page (path "/") because otherwise Apache will apply the rewriting rules +# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). +DirectoryIndex index.php + +# By default, Apache does not evaluate symbolic links if you did not enable this +# feature in your server configuration. Uncomment the following line if you +# install assets as symlinks or if you experience problems related to symlinks +# when compiling LESS/Sass/CoffeScript assets. +# Options +SymLinksIfOwnerMatch + +# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve +# to the front controller "/index.php" but be rewritten to "/index.php/index". + + Options -MultiViews + + + # This Option needs to be enabled for RewriteRule, otherwise it will show an error like + # 'Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden' + Options +SymLinksIfOwnerMatch + RewriteEngine On + # Determine the RewriteBase automatically and set it as environment variable. + # If you are using Apache aliases to do mass virtual hosting or installed the + # project in a subdirectory, the base path will be prepended to allow proper + # resolution of the index.php file and to redirect to the correct URI. It will + # work in environments without path prefix as well, providing a safe, one-size + # fits all solution. But as you do not need it in this case, you can comment + # the following 2 lines to eliminate the overhead. + RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$ + RewriteRule .* - [E=BASE:%1] + + # Sets the HTTP_AUTHORIZATION header removed by Apache + RewriteCond %{HTTP:Authorization} .+ + RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] + + # Redirect to URI without front controller to prevent duplicate content + # (with and without `/index.php`). Only do this redirect on the initial + # rewrite by Apache and not on subsequent cycles. Otherwise we would get an + # endless redirect loop (request -> rewrite to front controller -> + # redirect -> request -> ...). + # So in case you get a "too many redirects" error or you always get redirected + # to the start page because your Apache does not expose the REDIRECT_STATUS + # environment variable, you have 2 choices: + # - disable this feature by commenting the following 2 lines or + # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the + # following RewriteCond (best solution) + RewriteCond %{ENV:REDIRECT_STATUS} ="" + RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L] + + # If the requested filename exists, simply serve it. + # We only want to let Apache serve files and not directories. + # Rewrite all other queries to the front controller. RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^ index.php [QSA,L] + RewriteRule ^ %{ENV:BASE}/index.php [L] + + + + + # When mod_rewrite is not available, we instruct a temporary redirect of + # the start page to the front controller explicitly so that the website + # and the generated links can still be used. + RedirectMatch 307 ^/$ /index.php/ + # RedirectTemp cannot be used instead + diff --git a/public/index.php b/public/index.php index 3d3b096..7fbc8cf 100644 --- a/public/index.php +++ b/public/index.php @@ -1,34 +1,9 @@ addRoutingMiddleware(); - -/* - * Load settings - */ -require __DIR__ . '/../src/settings.php'; -require __DIR__ . '/../src/database.php'; - -// Add Error Middleware -$display_errors = false; -if (getenv('QANB_ENV') === 'staging' || getenv('QANB_ENV') === 'testing') { - $display_errors = true; -} -$errorMiddleware = $app->addErrorMiddleware($display_errors, $display_errors, $display_errors); -/** @var ErrorHandler */ -$defaultHandler = $errorMiddleware->getDefaultErrorHandler(); -$defaultHandler->forceContentType('application/json'); - -$app->run(); +return function (array $context) { + return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); +}; diff --git a/src/Command/ImportCommand.php b/src/Command/ImportCommand.php new file mode 100644 index 0000000..ab7927e --- /dev/null +++ b/src/Command/ImportCommand.php @@ -0,0 +1,84 @@ +reportImporter = $reportImporter; + $this->nightlyGCPUrl = $nightlyGCPUrl; + } + + protected function configure(): void + { + $this + ->addArgument('filename', InputArgument::REQUIRED) + ->addOption('platform', 'p', InputOption::VALUE_REQUIRED, '', ReportImporter::FILTER_PLATFORMS[0], ReportImporter::FILTER_PLATFORMS) + ->addOption('campaign', 'c', InputOption::VALUE_REQUIRED, '', ReportImporter::FILTER_CAMPAIGNS[0], ReportImporter::FILTER_CAMPAIGNS) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}-(.*)?\.json/', $input->getArgument('filename'), $matchesVersion); + if (!isset($matchesVersion[1]) || strlen($matchesVersion[1]) < 1) { + $output->writeln(sprintf( + 'Version found not correct (%s) from filename %s', + $matchesVersion[1], + $input->getArgument('filename') + )); + + return Command::FAILURE; + } + + $fileContent = @file_get_contents($this->nightlyGCPUrl . 'reports/' . $input->getArgument('filename')); + if (!$fileContent) { + $output->writeln('Unable to retrieve content from GCP URL'); + + return Command::FAILURE; + } + + $jsonContent = json_decode($fileContent); + if (!$jsonContent) { + $output->writeln('Unable to decode JSON data'); + + return Command::FAILURE; + } + + $dateformat = $input->getOption('campaign') === 'autoupgrade' + ? ReportImporter::FORMAT_DATE_MOCHA5 + : ReportImporter::FORMAT_DATE_MOCHA6; + $startDate = \DateTime::createFromFormat( + $dateformat, + $jsonContent->stats->start + ); + + $this->reportImporter->import( + $input->getArgument('filename'), + $input->getOption('platform'), + $input->getOption('campaign'), + $matchesVersion[1], + $startDate, + $jsonContent, + $dateformat + ); + + return Command::SUCCESS; + } +} diff --git a/src/Controller/BaseController.php b/src/Controller/BaseController.php deleted file mode 100644 index 55115ef..0000000 --- a/src/Controller/BaseController.php +++ /dev/null @@ -1,36 +0,0 @@ -where('name', '=', 'version')->first(); - $version = $version->value; - if ($version != QANB_VERSION) { - throw new Exception('wrong database version, please update.'); - } - } -} diff --git a/src/Controller/DataController.php b/src/Controller/DataController.php index 86160a8..aaa1b81 100644 --- a/src/Controller/DataController.php +++ b/src/Controller/DataController.php @@ -1,113 +1,104 @@ getBadgeData($request); - $badge = [ - 'schemaVersion' => 1, - 'label' => $badge_data['branch'], - 'message' => $badge_data['percent'] . '% passed', - 'color' => 'green', - ]; + $this->executionRepository = $executionRepository; + } - if ($badge_data['percent'] < 100) { - $badge['color'] = 'orange'; - } - if ($badge_data['percent'] < 80) { - $badge['color'] = 'red'; + #[Route('/data/badge', methods: ['GET'])] + public function badgeJson(Request $request): JsonResponse + { + $badge_data = $this->getBadgeData($request, false); + if (!$badge_data) { + return new JsonResponse([ + 'message' => 'Execution not found', + ], Response::HTTP_NOT_FOUND); } - $response->getBody()->write(json_encode($badge)); - - return $response->withHeader('Content-Type', 'application/json'); + return new JsonResponse([ + 'schemaVersion' => 1, + 'label' => $badge_data['branch'], + 'message' => $badge_data['percent'] . '% passed', + 'color' => $badge_data['color'], + ]); } - public function svg(Request $request, Response $response): Response + #[Route('/data/badge/svg', methods: ['GET'])] + public function badgeSvg(Request $request): Response { - $badge_data = $this->getBadgeData($request); - $color = '#76ca00'; //green - if ($badge_data['percent'] < 100) { - $color = '#eba400'; //orange - } - if ($badge_data['percent'] < 80) { - $color = '#e00707'; //red + $badge_data = $this->getBadgeData($request, true); + if (!$badge_data) { + return new Response('Execution not found', Response::HTTP_NOT_FOUND); } - $svg = ' - - - - - - ' . $badge_data['branch'] . ' - ' . $badge_data['percent'] . '% passed - - - '; - $response->getBody()->write($svg); + $content = sprintf( + '' + . '' + . '' + . '' + . '' + . '' + . '%s' + . '%.2f%% passed' + . '' + . '', + $badge_data['color'], + $badge_data['branch'], + $badge_data['percent'] + ); - return $response->withHeader('Content-Type', 'image/svg+xml'); + return new Response( + $content, + Response::HTTP_OK, + [ + 'content-type' => 'image/svg+xml', + ] + ); } /** - * Get all data for badges + * @return array{'branch': string, 'percent': float, 'color': string}|null */ - private function getBadgeData(Request $request): ?array - { - $badge = null; - //default values - $branch = 'develop'; - $date = null; - //check GET values - $get_query_params = $request->getQueryParams(); - if (isset($get_query_params['branch']) && trim($get_query_params['branch']) != '') { - $branch = trim($get_query_params['branch']); + private function getBadgeData( + Request $request, + bool $hexColor + ): ?array { + $branch = (string) $request->query->get('branch', 'develop'); + $date = $request->query->get('date'); + if ($date) { + $date = date('Y-m-d', strtotime($date)) == $date ? $date : null; } - if (isset($get_query_params['date']) && trim($get_query_params['date']) != '' - && date('Y-m-d', strtotime($get_query_params['date'])) == $get_query_params['date']) { - $date = trim($get_query_params['date']); - } + $execution = $this->executionRepository->findOneByVersionAndDate($branch, $date); + if ($execution) { + $percent = round(($execution->getPasses() * 100) / ($execution->getTests() - $execution->getPending() - $execution->getSkipped()), 2); - if ($date === null) { - $execution = Manager::table('execution') - ->where('version', '=', $branch) - ->orderBy('start_date', 'DESC') - ->limit(1) - ->first(); - } else { - $execution = Manager::table('execution') - ->where('version', '=', $branch) - ->whereRaw('DATE(start_date) = ?', [$date]) - ->first(); - } + if ($hexColor) { + $color = $percent < 80 ? '#e00707' : ($percent == 100 ? '#76ca00' : '#eba400'); + } else { + $color = $percent < 80 ? 'red' : ($percent == 100 ? 'green' : 'orange'); + } - if ($execution) { - $percent = round($execution->passes * 100 / ($execution->tests - $execution->pending - $execution->skipped), 2); - $badge = [ + return [ 'branch' => $branch, 'percent' => $percent, + 'color' => $color, ]; } - return $badge; + return null; } } diff --git a/src/Controller/GraphController.php b/src/Controller/GraphController.php index e38b009..e1d7e41 100644 --- a/src/Controller/GraphController.php +++ b/src/Controller/GraphController.php @@ -1,114 +1,104 @@ executionRepository = $executionRepository; + } + + #[Route('/graph', methods: ['GET'])] + public function data(Request $request): JsonResponse { - //possible values $parameters = $this->getParameters(); - //check GET values - $get_query_params = $request->getQueryParams(); - $period = $parameters['periods']['default']; - $version = $parameters['versions']['default']; - if (isset($get_query_params['period']) && $this->isValidParameter($get_query_params['period'], $parameters['periods']['values'])) { - $period = $get_query_params['period']; + $period = $request->query->get('period', self::DEFAULT_PERIOD); + if (!$this->isValidParameter($period, $parameters['periods']['values'])) { + $period = self::DEFAULT_PERIOD; } - if (isset($get_query_params['version']) && $this->isValidParameter($get_query_params['version'], $parameters['versions']['values'])) { - $version = $get_query_params['version']; + $version = $request->query->get('version', self::DEFAULT_VERSION); + if (!$this->isValidParameter($version, $parameters['versions']['values'])) { + $version = self::DEFAULT_VERSION; } switch ($period) { case 'last_two_months': - $start_date = date('Y-m-d', strtotime(' -60 days')); - $end_date = date('Y-m-d', strtotime(' +1 days')); + $dateStartBase = date('Y-m-d', strtotime(' -60 days')); + $dateEndBase = date('Y-m-d', strtotime(' +1 days')); break; case 'last_year': - $start_date = date('Y-m-d', strtotime(' -1 years')); - $end_date = date('Y-m-d', strtotime(' +1 days')); + $dateStartBase = date('Y-m-d', strtotime(' -1 years')); + $dateEndBase = date('Y-m-d', strtotime(' +1 days')); break; default: - $start_date = date('Y-m-d', strtotime(' -30 days')); - $end_date = date('Y-m-d', strtotime(' +1 days')); + $dateStartBase = date('Y-m-d', strtotime(' -30 days')); + $dateEndBase = date('Y-m-d', strtotime(' +1 days')); } - - if (isset($get_query_params['start_date']) && date('Y-m-d', strtotime($get_query_params['start_date'])) == $get_query_params['start_date']) { - $start_date = $get_query_params['start_date']; + $dateStart = $request->query->get('start_date', $dateStartBase); + if (date('Y-m-d', strtotime($dateStart)) !== $dateStart) { + $dateStart = $dateStartBase; } - if (isset($get_query_params['end_date']) && date('Y-m-d', strtotime($get_query_params['end_date'])) == $get_query_params['end_date']) { - $end_date = $get_query_params['end_date']; + $dateEnd = $request->query->get('end_date', $dateEndBase); + if (date('Y-m-d', strtotime($dateStart)) !== $dateEnd) { + $dateEnd = $dateEndBase; } - //get the data - $executions = Execution::getGraphData($version, $start_date, $end_date); - - $response->getBody()->write(json_encode($executions)); + $executions = []; + foreach ($this->executionRepository->findAllBetweenDates($version, $dateStart, $dateEnd) as $execution) { + $executions[] = [ + 'id' => $execution->getId(), + 'start_date' => $execution->getStartDate()->format('Y-m-d H:i:s'), + 'end_date' => $execution->getEndDate()->format('Y-m-d H:i:s'), + 'version' => $execution->getVersion(), + 'suites' => $execution->getSuites(), + 'tests' => $execution->getTests(), + 'skipped' => $execution->getSkipped(), + 'passes' => $execution->getPasses(), + 'failures' => $execution->getFailures(), + 'pending' => $execution->getPending(), + ]; + } - return $response->withHeader('Content-Type', 'application/json'); + return new JsonResponse($executions); } - /** - * Retrieve the list of all the available parameters - * - * @param Request $request - * @param Response $response - * - * @return Response - */ - public function parameters(Request $request, Response $response): Response + #[Route('/graph/parameters', methods: ['GET'])] + public function parameters(Request $request): JsonResponse { - $response->getBody()->write(json_encode($this->getParameters())); - - return $response->withHeader('Content-Type', 'application/json'); + return new JsonResponse($this->getParameters()); } /** * Format a list of all the parameters to use in all methods + * + * @return array{'periods': array{'type': string, 'name': string, 'values': array, 'default': string}, 'versions': array{'type': string, 'name': string, 'values': array, 'default': string}} */ private function getParameters(): array { - //versions - $versions_possible_values = ['develop']; - $versions_possible_values_from_base = Manager::table('execution') - ->select('version') - ->groupBy('version') - ->get(); - - if (!empty($versions_possible_values_from_base)) { - foreach ($versions_possible_values_from_base as $v) { - if (!in_array($v->version, $versions_possible_values)) { - $versions_possible_values[] = $v->version; - } - } - } - $versions_values = []; - foreach ($versions_possible_values as $v) { - $versions_values[] = [ - 'name' => ucfirst($v), - 'value' => $v, + $versions = []; + foreach (array_merge([self::DEFAULT_VERSION], $this->executionRepository->findAllVersions()) as $version) { + $versions[] = [ + 'name' => ucfirst($version), + 'value' => $version, ]; } - //periods - $periods_values = [ + + $periods = [ [ 'name' => 'Last 30 days', - 'value' => 'last_month', + 'value' => self::DEFAULT_PERIOD, ], [ 'name' => 'Last 60 days', @@ -124,25 +114,27 @@ private function getParameters(): array 'periods' => [ 'type' => 'select', 'name' => 'period', - 'values' => $periods_values, - 'default' => $periods_values[0]['value'], + 'values' => $periods, + 'default' => self::DEFAULT_PERIOD, ], 'versions' => [ 'type' => 'select', 'name' => 'version', - 'values' => $versions_values, - 'default' => $versions_values[0]['value'], + 'values' => $versions, + 'default' => self::DEFAULT_VERSION, ], ]; } /** * Check is the parameter is valid + * + * @param array $values */ private function isValidParameter(string $parameter, array $values): bool { foreach ($values as $value) { - if ($parameter == $value['value']) { + if ($parameter === $value['value']) { return true; } } diff --git a/src/Controller/HealthCheckController.php b/src/Controller/HealthCheckController.php index a521a1e..c338676 100644 --- a/src/Controller/HealthCheckController.php +++ b/src/Controller/HealthCheckController.php @@ -1,25 +1,23 @@ executionRepository = $executionRepository; + } + + #[Route('/healthcheck', methods: ['GET'])] + public function check(string $nightlyGCPUrl): JsonResponse { $data = [ 'database' => true, @@ -28,19 +26,21 @@ public function check(Request $request, Response $response): Response // Check database try { - Manager::table('settings')->first(); - } catch (QueryException $e) { + $this->executionRepository->findOneBy([ + 'version' => 'develop', + 'campaign' => 'functional', + 'platform' => 'chromium', + ]); + } catch (\Exception $e) { $data['database'] = false; } // Check GCP - $gcpCall = file_get_contents(QANB_GCPURL); + $gcpCall = @file_get_contents($nightlyGCPUrl); if (!$gcpCall) { $data['gcp'] = false; } - $response->getBody()->write(json_encode($data)); - - return $response->withHeader('Content-Type', 'application/json'); + return $this->json($data); } } diff --git a/src/Controller/ImportController.php b/src/Controller/ImportController.php new file mode 100644 index 0000000..a125e06 --- /dev/null +++ b/src/Controller/ImportController.php @@ -0,0 +1,173 @@ +executionRepository = $executionRepository; + $this->reportImporter = $reportImporter; + $this->nightlyToken = $nightlyToken; + $this->nightlyGCPUrl = $nightlyGCPUrl; + } + + #[Route('/hook/add', methods: ['GET'])] + /** Used in 1.7.7 & autoupgrade */ + public function importReportOld(Request $request): JsonResponse + { + $response = $this->checkAuth($request, ReportImporter::FORMAT_DATE_MOCHA5); + if ($response instanceof JsonResponse) { + return $response; + } + + $execution = $this->reportImporter->import( + $this->filename, + $this->platform, + $this->campaign, + $this->version, + $this->startDate, + $this->jsonContent, + ReportImporter::FORMAT_DATE_MOCHA5 + ); + + return new JsonResponse([ + 'status' => 'ok', + 'report' => $execution->getId(), + ]); + } + + #[Route('/hook/reports/import', methods: ['GET'])] + /** Used in 1.7.8+ */ + public function importReport(Request $request): JsonResponse + { + $response = $this->checkAuth($request, ReportImporter::FORMAT_DATE_MOCHA6); + if ($response instanceof JsonResponse) { + return $response; + } + + $execution = $this->reportImporter->import( + $this->filename, + $this->platform, + $this->campaign, + $this->version, + $this->startDate, + $this->jsonContent, + ReportImporter::FORMAT_DATE_MOCHA6 + ); + + return new JsonResponse([ + 'status' => 'ok', + 'report' => $execution->getId(), + ]); + } + + private function checkAuth(Request $request, string $dateFormat): ?JsonResponse + { + $token = $request->query->get('token'); + $this->filename = $request->query->get('filename'); + + if (!$token || !$this->filename) { + return new JsonResponse([ + 'message' => 'No enough parameters', + ], Response::HTTP_BAD_REQUEST); + } + if ($token !== $this->nightlyToken) { + return new JsonResponse([ + 'message' => 'Invalid token', + ], Response::HTTP_UNAUTHORIZED); + } + + preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}-(.*)?\.json/', $this->filename, $matchesVersion); + if (!isset($matchesVersion[1])) { + return new JsonResponse([ + 'message' => 'Could not retrieve version from filename', + ], Response::HTTP_BAD_REQUEST); + } + + $this->version = $matchesVersion[1]; + if (strlen($this->version) < 1) { + return new JsonResponse([ + 'message' => sprintf( + 'Version found not correct (%s) from filename %s', + $this->version, + $this->filename + ), + ], Response::HTTP_BAD_REQUEST); + } + + $fileContent = @file_get_contents($this->nightlyGCPUrl . 'reports/' . $this->filename); + if (!$fileContent) { + return new JsonResponse([ + 'message' => 'Unable to retrieve content from GCP URL', + ], Response::HTTP_BAD_REQUEST); + } + + $this->jsonContent = json_decode($fileContent); + if (!$this->jsonContent) { + return new JsonResponse([ + 'message' => 'Unable to decode JSON data', + ], Response::HTTP_BAD_REQUEST); + } + + $force = $request->query->get('force', false); + $force = is_bool($force) ? $force : false; + + $this->platform = $request->query->has('platform') ? $request->query->get('platform') : ( + $request->query->has('browser') ? $request->query->get('browser') : null + ); + $this->platform = in_array($this->platform, ReportImporter::FILTER_PLATFORMS) ? $this->platform : ReportImporter::FILTER_PLATFORMS[0]; + + $this->campaign = $request->query->has('campaign') ? $request->query->get('campaign') : null; + $this->campaign = in_array($this->campaign, ReportImporter::FILTER_CAMPAIGNS) ? $this->campaign : ReportImporter::FILTER_CAMPAIGNS[0]; + + $this->startDate = \DateTime::createFromFormat($dateFormat, $this->jsonContent->stats->start); + + // Check if there is no similar entry + if (!$force && $this->executionRepository->findOneByNightly($this->version, $this->platform, $this->campaign, $this->startDate->format('Y-m-d'))) { + return new JsonResponse([ + 'message' => sprintf( + 'A similar entry was found (criteria: version %s, platform %s, campaign %s, date %s).', + $this->version, + $this->platform, + $this->campaign, + $this->startDate->format('Y-m-d') + ), + ], Response::HTTP_FORBIDDEN); + } + + return null; + } +} diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php new file mode 100644 index 0000000..a8fb2fc --- /dev/null +++ b/src/Controller/IndexController.php @@ -0,0 +1,16 @@ + 0, - 'totalFailures' => 0, - 'totalPending' => 0, - 'totalSkipped' => 0, - ]; + private ReportSuiteBuilder $reportSuiteBuilder; - private $paramsReportDefault = [ - 'search' => null, - 'filter_state' => [ - self::FILTER_STATE_FAILED, - self::FILTER_STATE_PASSED, - self::FILTER_STATE_SKIPPED, - self::FILTER_STATE_PENDING, - ], - ]; + private string $nightlyGCPUrl; - private $paramsReport = []; + public function __construct( + ExecutionRepository $executionRepository, + ReportLister $reportLister, + ReportSuiteBuilder $reportSuiteBuilder, + string $nightlyGCPUrl + ) { + $this->executionRepository = $executionRepository; + $this->reportLister = $reportLister; + $this->reportSuiteBuilder = $reportSuiteBuilder; + $this->nightlyGCPUrl = $nightlyGCPUrl; + } - /** - * @param Request $request - * @param Response $response - * - * @return Response - */ - public function index(Request $request, Response $response): Response + #[Route('/reports', methods: ['GET'])] + public function reports(Request $request): JsonResponse { - $requestPlatform = $request->getQueryParams()['filter_platform'] - ?? ($request->getQueryParams()['filter_browser'] ?? false); - - $requestCampaign = isset($request->getQueryParams()['filter_campaign']) ? - $request->getQueryParams()['filter_campaign'] : false; + $executionFilters = []; - $requestVersion = isset($request->getQueryParams()['filter_version']) ? - $request->getQueryParams()['filter_version'] : false; - - //get all data from executions - $executions = Manager::table('execution'); - if ($requestPlatform) { - $executions = $executions->where('platform', '=', $requestPlatform); + if ($request->query->has('filter_platform')) { + $executionFilters['platform'] = $request->query->get('filter_platform'); + } elseif ($request->query->has('filter_browser')) { + $executionFilters['platform'] = $request->query->get('filter_browser'); } - if ($requestCampaign) { - $executions = $executions->where('campaign', '=', $requestCampaign); + if ($request->query->has('filter_campaign')) { + $executionFilters['campaign'] = $request->query->get('filter_campaign'); } - if ($requestVersion) { - $executions = $executions->where('version', '=', $requestVersion); + if ($request->query->has('filter_version')) { + $executionFilters['version'] = $request->query->get('filter_version'); } - $executions = $executions - ->orderBy('start_date', 'desc') - ->get(); + $executions = $this->executionRepository->findBy($executionFilters, [ + 'start_date' => 'DESC', + ]); - $GCP_files_list = []; - if (!$requestPlatform && !$requestCampaign) { - //get all data from GCP - //no need to get these data if we filtered by platform or campaign - $GCP_files_list = $this->getDataFromGCP(QANB_GCPURL); + $reportListing = []; + if (!isset($executionFilters['platform']) && !isset($executionFilters['campaign'])) { + // Get all data from GCP + // No need to get these data if we filtered by platform or campaign + $reportListing = $this->reportLister->get(); } - $full_list = []; + $reports = []; foreach ($executions as $execution) { - $download = null; - if (isset($GCP_files_list[date('Y-m-d', strtotime($execution->start_date))][$execution->version]['zip'])) { - $download = QANB_GCPURL . $GCP_files_list[date('Y-m-d', strtotime($execution->start_date))][$execution->version]['zip']; - } - $xml = null; - if (isset($GCP_files_list[date('Y-m-d', strtotime($execution->start_date))][$execution->version]['xml'])) { - $xml = QANB_GCPURL . $GCP_files_list[date('Y-m-d', strtotime($execution->start_date))][$execution->version]['xml']; - } - - $full_list[] = [ - 'id' => $execution->id, - 'date' => date('Y-m-d', strtotime($execution->start_date)), - 'version' => $execution->version, - 'campaign' => $execution->campaign, - 'browser' => $execution->platform, // retro-compatibility - 'platform' => $execution->platform, - 'start_date' => $execution->start_date, - 'end_date' => $execution->end_date, - 'duration' => $execution->duration, - 'suites' => $execution->suites, + $download = $xml = null; + $date = $execution->getStartDate()->format('Y-m-d'); + + if (isset($reportListing[$date][$execution->getVersion()]['zip'])) { + $download = $this->nightlyGCPUrl . $reportListing[$date][$execution->getVersion()]['zip']; + } + if (isset($reportListing[$date][$execution->getVersion()]['xml'])) { + $xml = $this->nightlyGCPUrl . $reportListing[$date][$execution->getVersion()]['xml']; + } + + $reports[] = [ + 'id' => $execution->getId(), + 'date' => $date, + 'version' => $execution->getVersion(), + 'campaign' => $execution->getCampaign(), + 'browser' => $execution->getPlatform(), // retro-compatibility + 'platform' => $execution->getPlatform(), + 'start_date' => $execution->getStartDate()->format('Y-m-d H:i:s'), + 'end_date' => $execution->getEndDate()->format('Y-m-d H:i:s'), + 'duration' => $execution->getDuration(), + 'suites' => $execution->getSuites(), 'tests' => [ - 'total' => ($execution->tests), - 'passed' => $execution->passes, - 'failed' => $execution->failures, - 'pending' => $execution->pending, - 'skipped' => $execution->skipped, + 'total' => $execution->getTests(), + 'passed' => $execution->getPasses(), + 'failed' => $execution->getFailures(), + 'pending' => $execution->getPending(), + 'skipped' => $execution->getSkipped(), ], - 'broken_since_last' => $execution->broken_since_last, - 'fixed_since_last' => $execution->fixed_since_last, - 'equal_since_last' => $execution->equal_since_last, + 'broken_since_last' => $execution->getBrokenSinceLast(), + 'fixed_since_last' => $execution->getFixedSinceLast(), + 'equal_since_last' => $execution->getEqualSinceLast(), 'download' => $download, 'xml' => $xml, ]; } - //merge two arrays in one and sort them by date - usort($full_list, function ($dt1, $dt2) { - $tm1 = isset($dt1['start_date']) ? $dt1['start_date'] : $dt1['date']; - $tm2 = isset($dt2['start_date']) ? $dt2['start_date'] : $dt2['date']; + // merge two arrays in one and sort them by date + usort($reports, function ($dt1, $dt2) { + $tm1 = $dt1['start_date']; + $tm2 = $dt2['start_date']; return ($tm1 < $tm2) ? 1 : (($tm1 > $tm2) ? -1 : 0); }); - $response->getBody()->write(json_encode($full_list)); - - return $response->withHeader('Content-Type', 'application/json'); + return new JsonResponse($reports); } - /** - * Display a single report information - * - * @param Request $request - * @param Response $response - * - * @return Response - * - * @throws NotFoundException - */ - public function report(Request $request, Response $response): Response + #[Route('/reports/{idReport}', methods: ['GET'])] + public function report(int $idReport, Request $request): JsonResponse { - $routeContext = RouteContext::fromRequest($request); - $route = $routeContext->getRoute(); - - $report_id = (int) $route->getArgument('report'); - - $this->paramsReport = array_merge($this->paramsReportDefault, $request->getQueryParams()); - - // Get all the data for this report - $execution = Manager::table('execution')->find($report_id); - + $execution = $this->executionRepository->findOneBy([ + 'id' => $idReport, + ]); if (!$execution) { - //error - throw new NotFoundException('Report not found'); - } - $execution_data = [ - 'id' => $execution->id, - 'date' => date('Y-m-d', strtotime($execution->start_date)), - 'version' => $execution->version, - 'campaign' => $execution->campaign, - 'browser' => $execution->platform, // retro-compatibility - 'platform' => $execution->platform, - 'start_date' => $execution->start_date, - 'end_date' => $execution->end_date, - 'duration' => $execution->duration, - 'suites' => $execution->suites, - 'tests' => $execution->tests, - 'broken_since_last' => $execution->broken_since_last, - 'fixed_since_last' => $execution->fixed_since_last, - 'equal_since_last' => $execution->equal_since_last, - 'skipped' => $execution->skipped, - 'pending' => $execution->pending, - 'passes' => $execution->passes, - 'failures' => $execution->failures, + return new JsonResponse([ + 'message' => 'Execution not found', + ], Response::HTTP_NOT_FOUND); + } + + $requestQueries = $request->query->all(); + $filters = []; + $filters['search'] = $requestQueries['search'] ?? null; + $filters['filter_state'] = $requestQueries['filter_state'] ?? ReportSuiteBuilder::FILTER_STATES; + + $return = [ + 'id' => $execution->getId(), + 'date' => $execution->getStartDate()->format('Y-m-d'), + 'version' => $execution->getVersion(), + 'campaign' => $execution->getCampaign(), + 'browser' => $execution->getPlatform(), // retro-compatibility + 'platform' => $execution->getPlatform(), + 'start_date' => $execution->getStartDate()->setTimezone(new \DateTimeZone('-01:00'))->format('Y-m-d H:i:s'), + 'end_date' => $execution->getEndDate()->setTimezone(new \DateTimeZone('-01:00'))->format('Y-m-d H:i:s'), + 'duration' => $execution->getDuration(), + 'suites' => $execution->getSuites(), + 'tests' => $execution->getTests(), + 'broken_since_last' => $execution->getBrokenSinceLast(), + 'fixed_since_last' => $execution->getFixedSinceLast(), + 'equal_since_last' => $execution->getEqualSinceLast(), + 'skipped' => $execution->getSkipped(), + 'pending' => $execution->getPending(), + 'passes' => $execution->getPasses(), + 'failures' => $execution->getFailures(), + 'suites_data' => $this->reportSuiteBuilder + ->filterStates($filters['filter_state']) + ->filterSearch($filters['search']) + ->build($execution) + ->toArray(), ]; - $suites = $this->getReportData($report_id); - $testsData = $this->getTestData($report_id); - - // Find if there is main suite id - $hasOnlyOneMainSuite = false; - foreach ($suites as $suite) { - if ($suite->parent_id === null) { - if ($hasOnlyOneMainSuite === false) { - $hasOnlyOneMainSuite = true; - $this->mainSuiteId = $suite->id; - } else { - // There is another suite with null, so not only one is used - // Used for legacy purpose - $hasOnlyOneMainSuite = false; - $this->mainSuiteId = null; - break; - } - } - } - - //build the recursive tree - $suites = $this->buildTree($suites, $testsData, $this->mainSuiteId); - $suites = $this->getRootSuitesAggregatedData($suites); - $suites = $this->filterSuitesByRootData($suites); - $suites = $this->filterTree($suites); - //put suites data into the final object - $execution_data['suites_data'] = $suites; - $response->getBody()->write(json_encode($execution_data)); - - return $response->withHeader('Content-Type', 'application/json'); + return new JsonResponse($return); } - /** - * Delete a report - needs the token - * - * @param Request $request - * @param Response $response - * - * @return Response - * - * @throws HttpBadRequestException - * @throws NotFoundException - */ - public function delete(Request $request, Response $response): Response + #[Route('/reports/{idReport}/suites/{idSuite}', methods: ['GET'])] + public function reportSuite(int $idReport, int $idSuite, Request $request): JsonResponse { - $this->authenticateHeaderToken($request); - //check if report exists - $routeContext = RouteContext::fromRequest($request); - $route = $routeContext->getRoute(); - $report_id = $route->getArgument('report'); - $execution = Manager::table('execution')->find($report_id); - + $execution = $this->executionRepository->findOneBy([ + 'id' => $idReport, + ]); if (!$execution) { - throw new NotFoundException('Report not found'); - } - - //here we go... - $delete = Manager::table('execution')->where('id', '=', $report_id)->delete(); - - $response->getBody()->write(json_encode([ - 'status' => 'ok', - ])); - - return $response->withHeader('Content-Type', 'application/json'); - } - - /** - * Display a single suite information - * - * @param Request $request - * @param Response $response - * - * @return Response - */ - public function suite(Request $request, Response $response): Response - { - $routeContext = RouteContext::fromRequest($request); - $route = $routeContext->getRoute(); - - $report_id = (int) $route->getArgument('report'); - $suiteId = (int) $route->getArgument('suite'); - - //get suite data - $root_suite = Manager::table('suite') - ->where('execution_id', '=', $report_id) - ->where('id', '=', $suiteId) - ->first(); - - if (!$root_suite) { - throw new NotFoundException('Suite not found for this execution'); - } - - //get tests for this root suite - $tests = Manager::table('test') - ->where('suite_id', '=', $suiteId) - ->get(); - $root_suite->tests = $tests; - - $children_suites = $this->getReportData($report_id); - $testsData = $this->getTestData($report_id); - //build the recursive tree - $suites = $this->buildTree($children_suites, $testsData, $suiteId); - $root_suite->suites = $suites; - //put suites data into the final object - $response->getBody()->write(json_encode($root_suite)); - - return $response->withHeader('Content-Type', 'application/json'); - } - - /** - * Import a new report data in the database - * - * @param Request $request - * @param Response $response - * - * @return Response - * - * @throws HttpBadRequestException - - * @throws HttpForbiddenException - */ - public function import(Request $request, Response $response): Response - { - $getQueryParams = $request->getQueryParams(); - $this->checkAuth($getQueryParams, $request); - $force = isset($getQueryParams['force']) && $getQueryParams['force'] == 'true'; - $platform = $this->getPlatform($getQueryParams); - $campaign = $this->getCampaign($getQueryParams); - $filename = $getQueryParams['filename']; - - $version = $this->getNumberVersion($filename, $request); - $fileContents = $this->getContents($filename, $request); - - //starting real stuff - $stats = $fileContents->stats; - $execution_data = [ - 'ref' => date('YmdHis'), - 'filename' => $filename, - 'platform' => $platform, - 'campaign' => $campaign, - 'start_date' => date('Y-m-d H:i:s', strtotime($stats->start)), - 'end_date' => date('Y-m-d H:i:s', strtotime($stats->end)), - 'duration' => $stats->duration, - 'version' => $version, - 'skipped' => $stats->skipped, - 'pending' => $stats->pending, - 'passes' => $stats->passes, - 'failures' => $stats->failures, - 'suites' => $stats->suites, - 'tests' => $stats->tests, - ]; - - //let's check if there's not a similar entry... - $entry_date = date('Y-m-d', strtotime($stats->start)); - $similar = Manager::table('execution') - ->where('version', '=', $version) - ->where('platform', '=', $platform) - ->where('campaign', '=', $campaign) - ->whereDate('start_date', '=', $entry_date) - ->first(); - if ($similar && !$force) { - throw new HttpForbiddenException($request, sprintf('A similar entry was found (criteria: version %s, platform %s, campaign %s, date %s).', $version, $platform, $campaign, $entry_date)); - } - //insert execution - $executionId = Manager::table('execution')->insertGetId($execution_data); - - foreach ($fileContents->results as $suite) { - $this->loopThroughSuite($executionId, $suite); - } - - $update_data = ['insertion_end_date' => Manager::Raw('NOW()')]; - - //calculate comparison with last execution - $comparison = $this->compareReportData($executionId); - if ($comparison) { - $update_data['broken_since_last'] = $comparison['broken']; - $update_data['fixed_since_last'] = $comparison['fixed']; - $update_data['equal_since_last'] = $comparison['equal']; - } - - Manager::table('execution') - ->where('id', '=', $executionId) - ->update($update_data); - - $response->getBody()->write(json_encode([ - 'status' => 'ok', - ])); - - return $response->withHeader('Content-Type', 'application/json'); - } - - /** - * Insert a new report data in the database - * - * @param Request $request - * @param Response $response - * - * @return Response - * - * @throws HttpBadRequestException - * @throws HttpForbiddenException - */ - public function insert(Request $request, Response $response): Response - { - $getQueryParams = $request->getQueryParams(); - $this->checkAuth($getQueryParams, $request); - $force = isset($getQueryParams['force']) && $getQueryParams['force'] == 'true'; - $platform = $this->getPlatform($getQueryParams); - $campaign = $this->getCampaign($getQueryParams); - $filename = $getQueryParams['filename']; - - $version = $this->getNumberVersion($filename, $request); - $fileContents = $this->getContents($filename, $request); - - //starting real stuff - $stats = $fileContents->stats; - $execution_data = [ - 'ref' => date('YmdHis'), - 'filename' => $filename, - 'platform' => $platform, - 'campaign' => $campaign, - 'start_date' => date('Y-m-d H:i:s', strtotime($stats->start)), - 'end_date' => date('Y-m-d H:i:s', strtotime($stats->end)), - 'duration' => $stats->duration, - 'version' => $version, - 'skipped' => $stats->skipped, - 'pending' => $stats->pending, - 'passes' => $stats->passes, - 'failures' => $stats->failures, - 'suites' => $stats->suites, - 'tests' => $stats->tests, - ]; - - //let's check if there's not a similar entry... - $entry_date = date('Y-m-d', strtotime($stats->start)); - $similar = Manager::table('execution') - ->where('version', '=', $version) - ->where('platform', '=', $platform) - ->where('campaign', '=', $campaign) - ->whereDate('start_date', '=', $entry_date) - ->first(); - if ($similar && !$force) { - throw new HttpForbiddenException($request, sprintf('A similar entry was found (criteria: version %s, platform %s, campaign %s, date %s).', $version, $platform, $campaign, $entry_date)); - } - //insert execution - $executionId = Manager::table('execution')->insertGetId($execution_data); - - $this->loopThrough($executionId, $fileContents->suites); - - $update_data = ['insertion_end_date' => Manager::Raw('NOW()')]; - - //calculate comparison with last execution - $comparison = $this->compareReportData($executionId); - if ($comparison) { - $update_data['broken_since_last'] = $comparison['broken']; - $update_data['fixed_since_last'] = $comparison['fixed']; - $update_data['equal_since_last'] = $comparison['equal']; - } - - Manager::table('execution') - ->where('id', '=', $executionId) - ->update($update_data); - - $response->getBody()->write(json_encode([ - 'status' => 'ok', - ])); - - return $response->withHeader('Content-Type', 'application/json'); - } - - /** - * Verify the token in headers - * - * @param Request $request - * - * @throws HttpBadRequestException - */ - private function authenticateHeaderToken(Request $request) - { - $headerValueArray = $request->getHeader('QANB_TOKEN'); - //check token - if (!isset($headerValueArray[0]) || $headerValueArray[0] != getenv('QANB_TOKEN')) { - throw new HttpBadRequestException($request, 'invalid token'); - } - } - - /** - * Filter suites by using root data (when using toggles) - */ - private function filterSuitesByRootData(array $suites): array - { - $paramsFilter = array_values($this->paramsReport['filter_state']); - foreach ($suites as $key => $root_suite) { - //when the "failed" toggle is turned on - if (in_array('failed', $paramsFilter) && $root_suite->childrenData['totalFailures'] > 0) { - continue; - } - //when the "pending" toggle is turned on - if (in_array('pending', $paramsFilter) && $root_suite->childrenData['totalPending'] > 0) { - continue; - } - //when the "skipped" toggle is turned on - if (in_array('skipped', $paramsFilter) && $root_suite->childrenData['totalSkipped'] > 0) { - continue; - } - //when the "passed" toggle is turned on and we didn't accept this suite, it must only be shown if - //it hasn't any pending or failed test - //this prevents showing a suite with passed and failed test when we hide failed tests for example - if (in_array('passed', $paramsFilter) && $root_suite->childrenData['totalPasses'] > 0 - && $root_suite->childrenData['totalFailures'] == 0 - && $root_suite->childrenData['totalSkipped'] == 0 - && $root_suite->childrenData['totalPending'] == 0) { - continue; - } - unset($suites[$key]); - } - - return $suites; - } - - /**Filter the whole tree when using fulltext search - * @param $suites - * @param callable|null $function - * @return array - */ - private function filterTree($suites, callable $function = null): array - { - foreach ($suites as $key => &$suiteChild) { - if (isset($suiteChild->suites) && is_array($suiteChild->suites)) { - $suiteChild->suites = $this->filterTree($suiteChild->suites, [$this, 'filterSuite']); - } - if (empty($suiteChild->suites) - && empty($suiteChild->tests) - && ($this->filterSuite($suiteChild) && empty($this->paramsReport['search']))) { - unset($suites[$key]); - } - } - - return array_filter($suites, [$this, 'filterSuite']); - } - - /** - * Filter suites - * - * @return bool - */ - private function filterSuite(stdClass $suite): bool - { - $status = true; - // If we need to search fulltext - if (!empty($this->paramsReport['search'])) { - $status = $this->filterSuiteSearch($suite, $this->paramsReport['search']); - } - - return $status; - } - - /** - * Filter each suite with text search in tests - * - * @return bool - */ - private function filterSuiteSearch(stdClass $suite, string $text): bool - { - // Title - if (stripos($suite->title, $text) !== false) { - return true; - } - // Tests - if (!empty($suite->tests)) { - foreach ($suite->tests as $test) { - if (stripos($test->title, $text) !== false) { - return true; - } - } - } - - return false; - } - - /** - * Method to render the whole suites tree - */ - private function buildTree(Collection $suites, array $testsData, ?int $parentId = null): array - { - $branch = []; - foreach ($suites as &$suite) { - // add tests in suite - if ($suite->hasTests == 1 && isset($testsData[$suite->id])) { - $suite->tests = $testsData[$suite->id]; - } - - if ($suite->parent_id == $parentId) { - $children = $this->buildTree($suites, $testsData, $suite->id); - - if ($children) { - $suite->suites = $children; - } - - $branch[$suite->id] = $suite; - unset($suite); - } - } - - return $branch; - } - - /** - * Loop through the whole suites tree to count all the tests children by state - */ - private function getRootSuitesAggregatedData(array $suites): array - { - foreach ($suites as $root_suite) { - $this->suiteChildrenData = [ - 'totalPasses' => 0, - 'totalFailures' => 0, - 'totalPending' => 0, - 'totalSkipped' => 0, - ]; - $this->loopThroughSuiteData($root_suite); - $root_suite->childrenData = $this->suiteChildrenData; - } - - return $suites; - } - - /** - * Recursive function to map all the tests - */ - private function loopThroughSuiteData(stdClass $suite) - { - $this->suiteChildrenData['totalPasses'] += $suite->totalPasses; - $this->suiteChildrenData['totalFailures'] += $suite->totalFailures; - $this->suiteChildrenData['totalPending'] += $suite->totalPending; - $this->suiteChildrenData['totalSkipped'] += $suite->totalSkipped; - if ($suite->hasSuites == 1) { - foreach ($suite->suites as $child_suite) { - $this->loopThroughSuiteData($child_suite); - } - } - } - - /** - * Get all the suites data from an execution - */ - private function getReportData(int $report_id): Collection - { - return Manager::table('suite') - ->where('execution_id', '=', $report_id) - ->orderBy('id') - ->get(); - } - - /** - * Get all the tests data from an execution - */ - private function getTestData(int $report_id): array - { - $tests = Manager::table('test') - ->join('suite', 'test.suite_id', '=', 'suite.id') - ->where('suite.execution_id', '=', $report_id) - ->select('test.*') - ->get(); - $testsData = []; - foreach ($tests as $test) { - if ($test->state == 'failed' && is_string($test->stack_trace)) { - $test->stack_trace_formatted = $this->formatStackTrace($test->stack_trace); - } - $testsData[$test->suite_id][] = $test; - } - - return $testsData; - } - - /** - * Format the stack_trace - */ - private function formatStackTrace(string $stack_trace): string - { - return str_replace(' at', '
    at', htmlentities($stack_trace)); - } - - /** - * Loop through data and insert it, recursive function - */ - private function loopThrough(int $executionId, stdClass $suite, ?int $parentSuiteId = null) - { - $dataSuite = [ - 'execution_id' => $executionId, - 'uuid' => $suite->uuid, - 'title' => $suite->title, - 'campaign' => $this->extractNames($suite->file, 'campaign'), - 'file' => $this->extractNames($suite->file, 'file'), - 'duration' => $suite->duration, - 'hasSkipped' => $suite->hasSkipped ? 1 : 0, - 'hasPending' => $suite->hasPending ? 1 : 0, - 'hasPasses' => $suite->hasPasses ? 1 : 0, - 'hasFailures' => $suite->hasFailures ? 1 : 0, - 'totalSkipped' => $suite->totalSkipped, - 'totalPending' => $suite->totalPending, - 'totalPasses' => $suite->totalPasses, - 'totalFailures' => $suite->totalFailures, - 'hasSuites' => $suite->hasSuites ? 1 : 0, - 'hasTests' => $suite->hasTests ? 1 : 0, - 'parent_id' => $parentSuiteId, - ]; - - //inserting current suite - $suiteId = Manager::table('suite')->insertGetId($dataSuite); - - if ($suiteId) { - //insert tests - if (count($suite->tests) > 0) { - foreach ($suite->tests as $test) { - $identifier = ''; - if (isset($test->context)) { - try { - $identifier_data = json_decode($test->context); - $identifier = is_array($identifier_data) ? $identifier_data[0]->value : $identifier_data->value; - } catch (Exception $e) { - } - } - $dataTest = [ - 'suite_id' => $suiteId, - 'uuid' => $test->uuid, - 'identifier' => $identifier, - 'title' => $test->title, - 'state' => $this->getTestState($test), - 'duration' => $test->duration, - 'error_message' => isset($test->err->message) ? $this->sanitize($test->err->message) : null, - 'stack_trace' => isset($test->err->estack) ? $this->sanitize($test->err->estack) : null, - 'diff' => isset($test->err->diff) ? $this->sanitize($test->err->diff) : null, - ]; - Manager::table('test')->insertGetId($dataTest); - } - } - //insert children suites - if (count($suite->suites) > 0) { - foreach ($suite->suites as $s) { - $this->loopThrough($executionId, $s, $suiteId); - } - } - } - } - - /** - * Loop through data and insert it, recursive function - */ - private function loopThroughSuite(int $executionId, stdClass $suite, ?int $parentSuiteId = null) - { - if (!empty($suite->root)) { - $suiteId = null; - } else { - $dataSuite = [ - 'execution_id' => $executionId, - 'uuid' => $suite->uuid, - 'title' => $suite->title, - 'campaign' => $this->extractNames($suite->file, 'campaign'), - 'file' => $this->extractNames($suite->file, 'file'), - 'duration' => $suite->duration, - 'hasSkipped' => !empty($suite->skipped), - 'hasPending' => !empty($suite->pending), - 'hasPasses' => !empty($suite->passes), - 'hasFailures' => !empty($suite->failures), - 'totalSkipped' => count($suite->skipped), - 'totalPending' => count($suite->pending), - 'totalPasses' => count($suite->passes), - 'totalFailures' => count($suite->failures), - 'hasSuites' => !empty($suite->suites), - 'hasTests' => !empty($suite->tests), - 'parent_id' => $parentSuiteId, - ]; - - //inserting current suite - $suiteId = Manager::table('suite')->insertGetId($dataSuite); - if (!$suiteId) { - return; - } - } - - //insert tests - foreach ($suite->tests as $test) { - $identifier = ''; - if (isset($test->context)) { - try { - $identifier_data = json_decode($test->context); - $identifier = is_array($identifier_data) ? $identifier_data[0]->value : $identifier_data->value; - } catch (Exception $e) { - // Don't care if it fails - } - } - - $dataTest = [ - 'suite_id' => $suiteId, - 'uuid' => $test->uuid, - 'identifier' => $identifier, - 'title' => $test->title, - 'state' => $this->getTestState($test), - 'duration' => $test->duration, - 'error_message' => isset($test->err->message) ? $this->sanitize($test->err->message) : null, - 'stack_trace' => isset($test->err->estack) ? $this->sanitize($test->err->estack) : null, - 'diff' => isset($test->err->diff) ? $this->sanitize($test->err->diff) : null, - ]; - Manager::table('test')->insertGetId($dataTest); - } - - //insert children suites - foreach ($suite->suites as $s) { - $this->loopThroughSuite($executionId, $s, $suiteId); - } - } - - /** - * @return array|bool - */ - public function compareReportData(int $id) - { - //get version and start_date of the given report - $tempData = Manager::table('execution') - ->select(['version', 'start_date', 'platform', 'campaign']) - ->where('id', '=', $id) - ->first(); - - //get id of the precedent report - $precedentReport = Manager::table('execution') - ->select('id') - ->where('version', '=', $tempData->version) - ->where('platform', '=', $tempData->platform) - ->where('campaign', '=', $tempData->campaign) - ->where('start_date', '<', $tempData->start_date) - ->orderBy('start_date', 'desc') - ->first(); - if (!$precedentReport) { - return false; - } - - // get comparison data between current report and precedent report - $data = Manager::table('test as t1') - ->select([ - 't1.state as old_test_state', - 't2.state as current_test_state', - ]) - ->join('suite as s1', 's1.id', '=', 't1.suite_id') - ->crossJoin('test as t2', function ($join) { - $join->on('t2.identifier', '=', 't1.identifier'); - $join->whereNotNull('t2.identifier'); - }) - ->join('suite as s2', 's2.id', '=', 't2.suite_id') - ->where('s1.execution_id', '=', $precedentReport->id) - ->where('s2.execution_id', '=', $id) - ->where('t1.identifier', '!=', 'loginBO') - ->where('t1.identifier', '!=', 'logoutBO') - ->where(function ($query) { - $query->where('t1.state', '=', 'failed') - ->orWhere('t2.state', '=', 'failed'); - }) - ->get(); - - if (count($data) > 0) { - $results = [ - 'fixed' => 0, - 'broken' => 0, - 'equal' => 0, - ]; - foreach ($data as $line) { - if ($line->old_test_state == 'failed' && $line->current_test_state == 'failed') { - ++$results['equal']; - } - if ($line->old_test_state == 'passed' && $line->current_test_state == 'failed') { - ++$results['broken']; - } - if ($line->old_test_state == 'failed' && $line->current_test_state == 'passed') { - ++$results['fixed']; - } - } - } else { - return false; - } - - return $results; - } - - /** - * Sanitize text by removing weird characters - */ - private function sanitize(string $text): string - { - $StrArr = str_split($text); - $NewStr = ''; - foreach ($StrArr as $Char) { - $CharNo = ord($Char); - if ($CharNo == 163) { - $NewStr .= $Char; - continue; - } - if ($CharNo > 31 && $CharNo < 127) { - $NewStr .= $Char; - } - } - - return $NewStr; - } - - /** - * Extract campaign name and file name from json data - * - * @return mixed|null - */ - private function extractNames(string $filename, string $type) - { - if (strlen($filename) == 0) { - return null; - } - if (strpos($filename, '/full/') !== false) { - //selenium - $pattern = '/\/full\/(.*?)\/(.*)/'; - preg_match($pattern, $filename, $matches); - if ($type == 'campaign') { - return isset($matches[1]) ? $matches[1] : null; - } - if ($type == 'file') { - return isset($matches[2]) ? $matches[2] : null; - } - } else { - //puppeteer - $pattern = '/\/campaigns\/(.*?)\/(.*?)\/(.*)/'; - preg_match($pattern, $filename, $matches); - if ($type == 'campaign') { - return isset($matches[2]) ? $matches[2] : null; - } - if ($type == 'file') { - return isset($matches[3]) ? $matches[3] : null; - } - } - - return null; - } - - /** - * Get the test state - */ - private function getTestState(stdClass $test): string - { - if (isset($test->state)) { - return $test->state; - } - if ($test->skipped == true) { - return 'skipped'; - } - if ($test->pending == true) { - return 'pending'; + return new JsonResponse([ + 'message' => 'Execution not found', + ], Response::HTTP_NOT_FOUND); } - return 'unknown'; - } + $return = $this->reportSuiteBuilder + ->filterSuite($idSuite) + ->filterEmptyArrays(false) + ->build($execution) + ->toArrayNth(0); - /** - * Format data from GCP (list of builds) - */ - private function getDataFromGCP(string $gcp_url): array - { - $GCP_files_list = []; - $GCPCallResult = file_get_contents($gcp_url); - if ($GCPCallResult) { - $xml = new \SimpleXMLElement($GCPCallResult); - foreach ($xml->Contents as $content) { - $build_name = (string) $content->Key; - foreach(['xml', 'zip'] as $extension) { - if (strpos($build_name, '.' . $extension) !== false) { - //get version and date - preg_match('/([0-9]{4}-[0-9]{2}-[0-9]{2})-([A-z0-9\.]*)-prestashop_(.*)\.' . $extension. '/', $build_name, $matches_filename); - if (count($matches_filename) == 4) { - $date = $matches_filename[1]; - $version = $matches_filename[2]; - if (!isset($GCP_files_list[$date][$version])) { - $GCP_files_list[$date][$version] = []; - } - $GCP_files_list[$date][$version][$extension] = $build_name; - } - } - } - } - } - - return $GCP_files_list; - } - - private function checkAuth(array $queryParams, $request): void - { - //check arguments in GET query - if (!isset($queryParams['token']) || !isset($queryParams['filename'])) { - throw new HttpBadRequestException($request, 'no enough parameters'); - } - //check token - if ($queryParams['token'] != getenv('QANB_TOKEN')) { - throw new HttpBadRequestException($request, 'invalid token'); - } - } - - private function getPlatform(array $queryParams): string - { - $platform = self::FILTER_PLATFORMS[0]; - $queryPlatform = $queryParams['platform'] ?? ($queryParams['browser'] ?? null); // retro-compatibility - if (null !== $queryPlatform && in_array($queryPlatform, self::FILTER_PLATFORMS)) { - $platform = $queryPlatform; - } - - return $platform; - } - - private function getCampaign(array $queryParams): string - { - $campaign = self::FILTER_CAMPAIGNS[0]; - if (isset($queryParams['campaign']) && in_array($queryParams['campaign'], self::FILTER_CAMPAIGNS)) { - $campaign = $queryParams['campaign']; - } - - return $campaign; - } - - private function getNumberVersion(string $filename, Request $request): string - { - //retrieving version number - preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}-(.*)?\.json/', $filename, $matches); - if (!isset($matches[1])) { - throw new HttpBadRequestException($request, 'could not retrieve version from filename'); - } - - $version = $matches[1]; - if (strlen($version) < 1) { - throw new HttpBadRequestException($request, sprintf('version found not correct (%s) from filename %s', $version, $filename)); - } - - return $version; - } - - private function getContents(string $filename, Request $request): stdClass - { - $url = QANB_GCPURL . 'reports/' . $filename; - $contents = file_get_contents($url); - if (!$contents) { - throw new HttpBadRequestException($request, 'unable to retrieve content from GCP URL'); - } - - //try to decode json - $fileContents = json_decode($contents); - if ($fileContents == null) { - throw new HttpBadRequestException($request, 'unable to decode JSON data'); - } + unset($return['childrenData']); - return $fileContents; + return new JsonResponse($return); } } diff --git a/src/Entity/Execution.php b/src/Entity/Execution.php new file mode 100644 index 0000000..c745555 --- /dev/null +++ b/src/Entity/Execution.php @@ -0,0 +1,354 @@ + */ + #[ORM\OneToMany(mappedBy: 'execution', targetEntity: Suite::class)] + private Collection $suitesCollection; + + public function __construct() + { + $this->suitesCollection = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function setId(int $id): static + { + $this->id = $id; + + return $this; + } + + public function getRef(): ?string + { + return $this->ref; + } + + public function setRef(string $ref): static + { + $this->ref = $ref; + + return $this; + } + + public function getFilename(): ?string + { + return $this->filename; + } + + public function setFilename(?string $filename): static + { + $this->filename = $filename; + + return $this; + } + + public function getStartDate(): ?\DateTime + { + return $this->start_date; + } + + public function setStartDate(?\DateTime $start_date): static + { + $this->start_date = $start_date; + + return $this; + } + + public function getEndDate(): ?\DateTime + { + return $this->end_date; + } + + public function setEndDate(?\DateTime $end_date): static + { + $this->end_date = $end_date; + + return $this; + } + + public function getDuration(): ?int + { + return $this->duration; + } + + public function setDuration(int $duration): static + { + $this->duration = $duration; + + return $this; + } + + public function getVersion(): ?string + { + return $this->version; + } + + public function setVersion(string $version): static + { + $this->version = $version; + + return $this; + } + + public function getCampaign(): string + { + return $this->campaign; + } + + public function setCampaign(string $campaign): static + { + $this->campaign = $campaign; + + return $this; + } + + public function getPlatform(): string + { + return $this->platform; + } + + public function setPlatform(string $platform): static + { + $this->platform = $platform; + + return $this; + } + + public function getSuites(): ?int + { + return $this->suites; + } + + public function setSuites(?int $suites): static + { + $this->suites = $suites; + + return $this; + } + + public function getTests(): ?int + { + return $this->tests; + } + + public function setTests(?int $tests): static + { + $this->tests = $tests; + + return $this; + } + + public function getSkipped(): ?int + { + return $this->skipped; + } + + public function setSkipped(?int $skipped): static + { + $this->skipped = $skipped; + + return $this; + } + + public function getPending(): ?int + { + return $this->pending; + } + + public function setPending(?int $pending): static + { + $this->pending = $pending; + + return $this; + } + + public function getPasses(): ?int + { + return $this->passes; + } + + public function setPasses(?int $passes): static + { + $this->passes = $passes; + + return $this; + } + + public function getFailures(): ?int + { + return $this->failures; + } + + public function setFailures(?int $failures): static + { + $this->failures = $failures; + + return $this; + } + + public function getBrokenSinceLast(): ?int + { + return $this->broken_since_last; + } + + public function setBrokenSinceLast(?int $broken_since_last): static + { + $this->broken_since_last = $broken_since_last; + + return $this; + } + + public function getFixedSinceLast(): ?int + { + return $this->fixed_since_last; + } + + public function setFixedSinceLast(?int $fixed_since_last): static + { + $this->fixed_since_last = $fixed_since_last; + + return $this; + } + + public function getEqualSinceLast(): ?int + { + return $this->equal_since_last; + } + + public function setEqualSinceLast(?int $equal_since_last): static + { + $this->equal_since_last = $equal_since_last; + + return $this; + } + + public function getInsertionStartDate(): ?\DateTimeInterface + { + return $this->insertion_start_date; + } + + public function setInsertionStartDate(\DateTimeInterface $insertion_start_date): static + { + $this->insertion_start_date = $insertion_start_date; + + return $this; + } + + public function getInsertionEndDate(): ?\DateTimeInterface + { + return $this->insertion_end_date; + } + + public function setInsertionEndDate(\DateTimeInterface $insertion_end_date): static + { + $this->insertion_end_date = $insertion_end_date; + + return $this; + } + + /** + * @return Collection + */ + public function getSuitesCollection(): Collection + { + return $this->suitesCollection; + } + + public function addSuite(Suite $suite): static + { + if (!$this->suitesCollection->contains($suite)) { + $this->suitesCollection->add($suite); + $suite->setExecution($this); + } + + return $this; + } + + public function removeSuite(Suite $suite): static + { + if ($this->suitesCollection->removeElement($suite)) { + // set the owning side to null (unless already changed) + if ($suite->getExecution() === $this) { + $suite->setExecution(null); + } + } + + return $this; + } +} diff --git a/src/Entity/Settings.php b/src/Entity/Settings.php new file mode 100644 index 0000000..90cfa5c --- /dev/null +++ b/src/Entity/Settings.php @@ -0,0 +1,58 @@ +id; + } + + public function setId(int $id): static + { + $this->id = $id; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } + + public function getValue(): ?string + { + return $this->value; + } + + public function setValue(string $value): static + { + $this->value = $value; + + return $this; + } +} diff --git a/src/Entity/Suite.php b/src/Entity/Suite.php new file mode 100644 index 0000000..7b5177f --- /dev/null +++ b/src/Entity/Suite.php @@ -0,0 +1,375 @@ + */ + #[ORM\OneToMany(mappedBy: 'suite', targetEntity: Test::class, orphanRemoval: true)] + private Collection $tests; + + /** @var array */ + private array $suites = []; + + public function __construct() + { + $this->tests = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function setId(int $id): static + { + $this->id = $id; + + return $this; + } + + public function getExecution(): ?Execution + { + return $this->execution; + } + + public function setExecution(?Execution $execution): static + { + $this->execution = $execution; + + return $this; + } + + public function getUuid(): ?string + { + return $this->uuid; + } + + public function setUuid(string $uuid): static + { + $this->uuid = $uuid; + + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getCampaign(): ?string + { + return $this->campaign; + } + + public function setCampaign(?string $campaign): static + { + $this->campaign = $campaign; + + return $this; + } + + public function getFile(): ?string + { + return $this->file; + } + + public function setFile(?string $file): static + { + $this->file = $file; + + return $this; + } + + public function getDuration(): ?int + { + return $this->duration; + } + + public function setDuration(?int $duration): static + { + $this->duration = $duration; + + return $this; + } + + public function hasSkipped(): ?bool + { + return $this->hasSkipped; + } + + public function setHasSkipped(?bool $hasSkipped): static + { + $this->hasSkipped = $hasSkipped; + + return $this; + } + + public function hasPending(): ?bool + { + return $this->hasPending; + } + + public function setHasPending(?bool $hasPending): static + { + $this->hasPending = $hasPending; + + return $this; + } + + public function hasPasses(): ?bool + { + return $this->hasPasses; + } + + public function setHasPasses(?bool $hasPasses): static + { + $this->hasPasses = $hasPasses; + + return $this; + } + + public function hasFailures(): ?bool + { + return $this->hasFailures; + } + + public function setHasFailures(bool $hasFailures): static + { + $this->hasFailures = $hasFailures; + + return $this; + } + + public function getTotalSkipped(): ?int + { + return $this->totalSkipped; + } + + public function setTotalSkipped(?int $totalSkipped): static + { + $this->totalSkipped = $totalSkipped; + + return $this; + } + + public function getTotalPending(): ?int + { + return $this->totalPending; + } + + public function setTotalPending(?int $totalPending): static + { + $this->totalPending = $totalPending; + + return $this; + } + + public function getTotalPasses(): ?int + { + return $this->totalPasses; + } + + public function setTotalPasses(?int $totalPasses): static + { + $this->totalPasses = $totalPasses; + + return $this; + } + + public function getTotalFailures(): ?int + { + return $this->totalFailures; + } + + public function setTotalFailures(?int $totalFailures): static + { + $this->totalFailures = $totalFailures; + + return $this; + } + + public function getHasSuites(): ?int + { + return $this->hasSuites; + } + + public function setHasSuites(?int $hasSuites): static + { + $this->hasSuites = $hasSuites; + + return $this; + } + + public function getHasTests(): ?int + { + return $this->hasTests; + } + + public function setHasTests(?int $hasTests): static + { + $this->hasTests = $hasTests; + + return $this; + } + + public function getParentId(): ?int + { + return $this->parent_id; + } + + public function setParentId(?int $parent_id): static + { + $this->parent_id = $parent_id; + + return $this; + } + + public function getInsertionDate(): ?\DateTime + { + return $this->insertion_date; + } + + public function setInsertionDate(\DateTime $insertion_date): static + { + $this->insertion_date = $insertion_date; + + return $this; + } + + /** + * @return Collection + */ + public function getTests(): Collection + { + return $this->tests; + } + + /** + * @param array $tests + */ + public function setTests(array $tests): static + { + foreach ($this->tests as $test) { + $this->removeTest($test); + } + foreach ($tests as $test) { + $this->addTest($test); + } + + return $this; + } + + public function addTest(Test $test): static + { + if (!$this->tests->contains($test)) { + $this->tests->add($test); + $test->setSuite($this); + } + + return $this; + } + + public function removeTest(Test $test): static + { + if ($this->tests->removeElement($test)) { + // set the owning side to null (unless already changed) + if ($test->getSuite() === $this) { + $test->setSuite(null); + } + } + + return $this; + } + + /** + * @return array + */ + public function getSuites(): array + { + return $this->suites; + } + + /** + * @param array $suites + */ + public function setSuites(array $suites): static + { + $this->suites = $suites; + + return $this; + } +} diff --git a/src/Entity/Test.php b/src/Entity/Test.php new file mode 100644 index 0000000..924c38d --- /dev/null +++ b/src/Entity/Test.php @@ -0,0 +1,193 @@ +id; + } + + public function setId(int $id): static + { + $this->id = $id; + + return $this; + } + + public function getSuite(): ?Suite + { + return $this->suite; + } + + public function setSuite(?Suite $suite): static + { + $this->suite = $suite; + + return $this; + } + + public function getUuid(): ?string + { + return $this->uuid; + } + + public function setUuid(string $uuid): static + { + $this->uuid = $uuid; + + return $this; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function setIdentifier(string $identifier): static + { + $this->identifier = $identifier; + + return $this; + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getState(): ?string + { + return $this->state; + } + + public function setState(?string $state): static + { + $this->state = $state; + + return $this; + } + + public function getDuration(): ?int + { + return $this->duration; + } + + public function setDuration(int $duration): static + { + $this->duration = $duration; + + return $this; + } + + public function getErrorMessage(): ?string + { + return $this->error_message; + } + + public function setErrorMessage(?string $error_message): static + { + $this->error_message = $error_message; + + return $this; + } + + public function getStackTrace(): ?string + { + return $this->stack_trace; + } + + public function setStackTrace(?string $stack_trace): static + { + $this->stack_trace = $stack_trace; + + return $this; + } + + public function getFormattedStackTrace(): ?string + { + return $this->formattedStackTrace; + } + + public function setFormattedStackTrace(?string $formattedStackTrace): static + { + $this->formattedStackTrace = $formattedStackTrace; + + return $this; + } + + public function getDiff(): ?string + { + return $this->diff; + } + + public function setDiff(?string $diff): static + { + $this->diff = $diff; + + return $this; + } + + public function getInsertionDate(): ?\DateTime + { + return $this->insertion_date; + } + + public function setInsertionDate(\DateTime $insertion_date): static + { + $this->insertion_date = $insertion_date; + + return $this; + } +} diff --git a/src/Kernel.php b/src/Kernel.php new file mode 100644 index 0000000..779cd1f --- /dev/null +++ b/src/Kernel.php @@ -0,0 +1,11 @@ += :start_date - AND `start_date` < :end_date - AND `version` = :version - ORDER BY `start_date` ASC;', ['start_date' => $start_date, 'end_date' => $end_date, 'version' => $version]); - } -} diff --git a/src/Repository/ExecutionRepository.php b/src/Repository/ExecutionRepository.php new file mode 100644 index 0000000..3dd5abf --- /dev/null +++ b/src/Repository/ExecutionRepository.php @@ -0,0 +1,121 @@ + + * + * @method Execution|null find($id, $lockMode = null, $lockVersion = null) + * @method Execution|null findOneBy(array $criteria, array $orderBy = null) + * @method Execution[] findAll() + * @method Execution[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ExecutionRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Execution::class); + } + + public function findOneByNightly( + string $version, + string $platform, + string $campaign, + string $date + ): ?Execution { + $qb = $this->createQueryBuilder('e') + ->andWhere('e.version = :version') + ->andWhere('e.platform = :platform') + ->andWhere('e.campaign = :campaign') + ->andWhere('DATE(e.start_date) = :date') + ->setParameter('version', $version) + ->setParameter('platform', $platform) + ->setParameter('campaign', $campaign) + ->setParameter('date', $date) + ->orderBy('e.start_date', 'DESC'); + + return $qb->getQuery() + ->setMaxResults(1) + ->getOneOrNullResult(); + } + + public function findOneByNightlyBefore( + string $version, + string $platform, + string $campaign, + \DateTimeInterface $dateUntil + ): ?Execution { + $qb = $this->createQueryBuilder('e') + ->andWhere('e.version = :version') + ->andWhere('e.platform = :platform') + ->andWhere('e.campaign = :campaign') + ->andWhere('e.start_date < :dateUntil') + ->setParameter('version', $version) + ->setParameter('platform', $platform) + ->setParameter('campaign', $campaign) + ->setParameter('dateUntil', $dateUntil) + ->orderBy('e.start_date', 'DESC'); + + return $qb->getQuery() + ->setMaxResults(1) + ->getOneOrNullResult(); + } + + public function findOneByVersionAndDate(string $version, ?string $date): ?Execution + { + $qb = $this->createQueryBuilder('e') + ->andWhere('e.version = :version') + ->setParameter('version', $version) + ->orderBy('e.start_date', 'DESC'); + + if ($date) { + $qb->andWhere('DATE(e.start_date) = :date') + ->setParameter('date', $date); + } + + return $qb->getQuery() + ->setMaxResults(1) + ->getOneOrNullResult(); + } + + /** + * @return array + */ + public function findAllVersions(): array + { + $results = ['develop']; + foreach ($this->createQueryBuilder('e') + ->select('e.version') + ->groupBy('e.version') + ->getQuery() + ->getResult() as $datum) { + if (in_array($datum['version'], $results)) { + continue; + } + $results[] = $datum['version']; + } + + return $results; + } + + /** + * @return array + */ + public function findAllBetweenDates(string $version, string $startDate, string $endDate): array + { + $qb = $this->createQueryBuilder('e') + ->andWhere('e.version = :version') + ->andWhere('e.start_date >= :start_date') + ->andWhere('e.start_date < :end_date') + ->setParameter('version', $version) + ->setParameter('start_date', $startDate) + ->setParameter('end_date', $endDate) + ->orderBy('e.start_date', 'ASC'); + + return $qb->getQuery()->getResult(); + } +} diff --git a/src/Repository/SettingsRepository.php b/src/Repository/SettingsRepository.php new file mode 100644 index 0000000..3a9f2cf --- /dev/null +++ b/src/Repository/SettingsRepository.php @@ -0,0 +1,23 @@ + + * + * @method Settings|null find($id, $lockMode = null, $lockVersion = null) + * @method Settings|null findOneBy(array $criteria, array $orderBy = null) + * @method Settings[] findAll() + * @method Settings[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class SettingsRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Settings::class); + } +} diff --git a/src/Repository/SuiteRepository.php b/src/Repository/SuiteRepository.php new file mode 100644 index 0000000..f08ad84 --- /dev/null +++ b/src/Repository/SuiteRepository.php @@ -0,0 +1,23 @@ + + * + * @method Suite|null find($id, $lockMode = null, $lockVersion = null) + * @method Suite|null findOneBy(array $criteria, array $orderBy = null) + * @method Suite[] findAll() + * @method Suite[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class SuiteRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Suite::class); + } +} diff --git a/src/Repository/TestRepository.php b/src/Repository/TestRepository.php new file mode 100644 index 0000000..34b8a63 --- /dev/null +++ b/src/Repository/TestRepository.php @@ -0,0 +1,52 @@ + + * + * @method Test|null find($id, $lockMode = null, $lockVersion = null) + * @method Test|null findOneBy(array $criteria, array $orderBy = null) + * @method Test[] findAll() + * @method Test[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class TestRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Test::class); + } + + /** + * Get comparison data between current report and precedent report + * + * @return array + */ + public function findComparisonDate(Execution $current, Execution $previous): array + { + return $this->createQueryBuilder('t1') + ->select([ + 't1.state as old_test_state', + 't2.state as current_test_state', + ]) + ->join('t1.suite', 's1') + ->leftJoin(Test::class, 't2', Expr\Join::WITH, 't2.identifier IS NOT NULL AND t2.identifier = t1.identifier') + ->join('t2.suite', 's2') + ->where('s1.execution = :previous') + ->andWhere('s2.execution = :current') + ->andWhere('t1.identifier != \'loginBO\'') + ->andWhere('t2.identifier != \'loginBO\'') + ->andWhere('(t1.state = \'failed\') OR (t2.state = \'failed\')') + ->setParameter('previous', $previous) + ->setParameter('current', $current) + ->getQuery() + ->getResult() + ; + } +} diff --git a/src/Service/ReportImporter.php b/src/Service/ReportImporter.php new file mode 100644 index 0000000..030aca2 --- /dev/null +++ b/src/Service/ReportImporter.php @@ -0,0 +1,258 @@ +entityManager = $entityManager; + $this->executionRepository = $executionRepository; + $this->testRepository = $testRepository; + } + + public function import( + string $filename, + string $platform, + string $campaign, + string $version, + \DateTime $startDate, + \stdClass $jsonContent, + string $dateformat + ): Execution { + $execution = new Execution(); + $execution + ->setRef(date('YmdHis')) + ->setFilename($filename) + ->setPlatform($platform) + ->setCampaign($campaign) + ->setStartDate($startDate) + ->setEndDate(\DateTime::createFromFormat($dateformat, $jsonContent->stats->end)) + ->setDuration($jsonContent->stats->duration) + ->setVersion($version) + ->setSuites($jsonContent->stats->suites) + ->setTests($jsonContent->stats->tests) + ->setSkipped($jsonContent->stats->skipped) + ->setPending($jsonContent->stats->pending) + ->setPasses($jsonContent->stats->passes) + ->setFailures($jsonContent->stats->failures) + ->setInsertionStartDate(new \DateTime()) + ; + $this->entityManager->persist($execution); + $this->entityManager->flush(); + + if ($dateformat == self::FORMAT_DATE_MOCHA5) { + $this->insertExecutionSuite($execution, $jsonContent->suites, $dateformat); + } else { + foreach ($jsonContent->results as $suite) { + if ($suite->root) { + foreach ($suite->suites as $suiteChild) { + $this->insertExecutionSuite($execution, $suiteChild, $dateformat); + } + } else { + $this->insertExecutionSuite($execution, $suite, $dateformat); + } + } + } + + // Calculate comparison with last execution + $execution = $this->compareReportData($execution); + $execution->setInsertionEndDate(new \DateTime()); + + $this->entityManager->persist($execution); + $this->entityManager->flush(); + + return $execution; + } + + private function insertExecutionSuite(Execution $execution, \stdClass $suite, string $dateFormat, int $parentSuiteId = null): void + { + $isMocha6 = $dateFormat === self::FORMAT_DATE_MOCHA6; + + $executionSuite = new Suite(); + $executionSuite + ->setExecution($execution) + ->setUuid($suite->uuid) + ->setTitle($suite->title) + ->setDuration($suite->duration) + ->setHasSkipped($isMocha6 ? (!empty($suite->skipped)) : ($suite->hasSkipped ? 1 : 0)) + ->setHasPending($isMocha6 ? (!empty($suite->pending)) : ($suite->hasPending ? 1 : 0)) + ->setHasPasses($isMocha6 ? (!empty($suite->passes)) : ($suite->hasPasses ? 1 : 0)) + ->setHasFailures($isMocha6 ? (!empty($suite->failures)) : ($suite->hasFailures ? 1 : 0)) + ->setHasSuites($isMocha6 ? (!empty($suite->suites)) : ($suite->hasSuites ? 1 : 0)) + ->setHasTests($isMocha6 ? (!empty($suite->tests)) : ($suite->hasTests ? 1 : 0)) + ->setTotalSkipped($isMocha6 ? (count($suite->skipped)) : ($suite->totalSkipped)) + ->setTotalPending($isMocha6 ? (count($suite->pending)) : ($suite->totalPending)) + ->setTotalPasses($isMocha6 ? (count($suite->passes)) : ($suite->totalPasses)) + ->setTotalFailures($isMocha6 ? (count($suite->failures)) : ($suite->totalFailures)) + ->setParentId($parentSuiteId) + ->setCampaign($this->extractDataFromFile($suite->file, 'campaign')) + ->setFile($this->extractDataFromFile($suite->file, 'file')) + ->setInsertionDate(new \DateTime()) + ; + $this->entityManager->persist($executionSuite); + $this->entityManager->flush(); + + // Insert tests + foreach ($suite->tests as $test) { + $identifier = ''; + if (!empty($test->context)) { + $identifier_data = json_decode($test->context); + $identifier = is_array($identifier_data) ? $identifier_data[0]->value : $identifier_data->value; + } + $executionTest = new Test(); + $executionTest + ->setSuite($executionSuite) + ->setUuid($test->uuid) + ->setTitle($test->title) + ->setDuration($test->duration) + ->setIdentifier($identifier) + ->setState($this->extractTestState($test)) + ->setErrorMessage(isset($test->err->message) ? $this->sanitize($test->err->message) : null) + ->setStackTrace(isset($test->err->estack) ? $this->sanitize($test->err->estack) : null) + ->setDiff(isset($test->err->diff) ? $this->sanitize($test->err->diff) : null) + ->setInsertionDate(new \DateTime()) + ; + $this->entityManager->persist($executionTest); + } + $this->entityManager->flush(); + + // Insert children suites + foreach ($suite->suites as $suiteChildren) { + $this->insertExecutionSuite($execution, $suiteChildren, $dateFormat, $executionSuite->getId()); + } + } + + /** + * Extract campaign name and file name from json data + */ + private function extractDataFromFile(string $filename, string $type): string + { + if (strlen($filename) == 0) { + return ''; + } + if (strpos($filename, '/full/') !== false) { + // Selenium + $pattern = '/\/full\/(.*?)\/(.*)/'; + preg_match($pattern, $filename, $matches); + if ($type == 'campaign') { + return isset($matches[1]) ? $matches[1] : ''; + } + if ($type == 'file') { + return isset($matches[2]) ? $matches[2] : ''; + } + } else { + // Puppeteer + $pattern = '/\/campaigns\/(.*?)\/(.*?)\/(.*)/'; + preg_match($pattern, $filename, $matches); + if ($type == 'campaign') { + return isset($matches[2]) ? $matches[2] : ''; + } + if ($type == 'file') { + return isset($matches[3]) ? $matches[3] : ''; + } + } + + return ''; + } + + private function extractTestState(\stdClass $test): string + { + if (isset($test->state)) { + return $test->state; + } + if ($test->skipped == true) { + return 'skipped'; + } + if ($test->pending == true) { + return 'pending'; + } + + return 'unknown'; + } + + /** + * Sanitize text by removing weird characters + */ + private function sanitize(string $text): string + { + $result = ''; + foreach (str_split($text) as $character) { + $ascii = ord($character); + if ($ascii == 163) { + $result .= $character; + continue; + } + if ($ascii > 31 && $ascii < 127) { + $result .= $character; + } + } + + return $result; + } + + private function compareReportData(Execution $execution): Execution + { + if (!$execution->getStartDate()) { + return $execution; + } + + $executionPrevious = $this->executionRepository->findOneByNightlyBefore( + $execution->getVersion(), + $execution->getPlatform(), + $execution->getCampaign(), + $execution->getStartDate() + ); + if (!$executionPrevious) { + return $execution; + } + + $data = $this->testRepository->findComparisonDate($execution, $executionPrevious); + if (empty($data)) { + return $execution; + } + + // Reset + $execution + ->setFixedSinceLast(0) + ->setBrokenSinceLast(0) + ->setEqualSinceLast(0) + ; + foreach ($data as $datum) { + if ($datum['old_test_state'] == 'failed' && $datum['current_test_state'] == 'failed') { + $execution->setEqualSinceLast($execution->getEqualSinceLast() + 1); + } + if ($datum['old_test_state'] == 'passed' && $datum['current_test_state'] == 'failed') { + $execution->setBrokenSinceLast($execution->getBrokenSinceLast() + 1); + } + if ($datum['old_test_state'] == 'failed' && $datum['current_test_state'] == 'passed') { + $execution->setFixedSinceLast($execution->getFixedSinceLast() + 1); + } + } + + return $execution; + } +} diff --git a/src/Service/ReportLister.php b/src/Service/ReportLister.php new file mode 100644 index 0000000..3dc439f --- /dev/null +++ b/src/Service/ReportLister.php @@ -0,0 +1,56 @@ +url = $nightlyGCPUrl; + } + + /** + * @return array>> + */ + public function get(): array + { + $return = file_get_contents($this->url); + if (!$return) { + return []; + } + + $listing = []; + + $xml = new \SimpleXMLElement($return); + foreach ($xml->Contents as $content) { + $buildName = (string) $content->Key; + + foreach (['xml', 'zip'] as $extension) { + if (strpos($buildName, '.' . $extension) === false) { + continue; + } + + // Extract version and date + preg_match( + '/([0-9]{4}-[0-9]{2}-[0-9]{2})-([A-z0-9\.]*)-prestashop_(.*)\.' . $extension . '/', + $buildName, + $matches + ); + if (count($matches) !== 4) { + continue; + } + + $date = $matches[1]; + $version = $matches[2]; + if (!isset($listing[$date][$version])) { + $listing[$date][$version] = []; + } + $listing[$date][$version][$extension] = $buildName; + } + } + + return $listing; + } +} diff --git a/src/Service/ReportSuiteBuilder.php b/src/Service/ReportSuiteBuilder.php new file mode 100644 index 0000000..939a6c7 --- /dev/null +++ b/src/Service/ReportSuiteBuilder.php @@ -0,0 +1,359 @@ + */ + private array $filterStates = self::FILTER_STATES; + + private ?string $filterSearch = null; + + private ?int $filterSuiteId = null; + + private bool $filterEmptyArrays = true; + + /** @var array */ + private array $suites = []; + + /** @var array> */ + private array $tests = []; + + /** @var array> */ + private array $stats = []; + + public function filterEmptyArrays(bool $filterEmptyArrays): self + { + $this->filterEmptyArrays = $filterEmptyArrays; + + return $this; + } + + public function filterSearch(string $search = null): self + { + $this->filterSearch = $search; + + return $this; + } + + /** + * @param array $states + */ + public function filterStates(array $states = self::FILTER_STATES): self + { + $this->filterStates = $states; + + return $this; + } + + public function filterSuite(int $suiteId = null): self + { + $this->filterSuiteId = $suiteId; + + return $this; + } + + public function build(Execution $execution): self + { + $this->suites = $execution->getSuitesCollection()->toArray(); + + // Find if there is main suite id + $hasOnlyOneMainSuite = false; + $mainSuiteId = null; + foreach ($this->suites as $suite) { + if ($suite->getParentId()) { + continue; + } + + if ($hasOnlyOneMainSuite) { + // There is another suite with null, so not only one is used + // Used for legacy purpose + $hasOnlyOneMainSuite = false; + $mainSuiteId = null; + break; + } + + $hasOnlyOneMainSuite = true; + $mainSuiteId = $suite->getId(); + } + // Extract tests + $this->tests = $this->getTests(); + + // Build the recursive tree + $this->suites = $this->buildTree($mainSuiteId, true); + $this->suites = $this->filterTree($this->suites); + + return $this; + } + + /** + * @return array + */ + public function toArrayNth(int $nth): array + { + $data = array_values($this->toArray()); + + return $data[$nth] ?? []; + } + + /** + * @return array> + */ + public function toArray(): array + { + $data = []; + + foreach ($this->suites as $suite) { + $data[$suite->getId()] = $this->formatSuite($suite); + } + + return $data; + } + + /** + * @return array + */ + private function formatSuite(Suite $suite): array + { + $suites = $tests = []; + foreach ($suite->getSuites() as $suiteChild) { + $suites[$suiteChild->getId()] = $this->formatSuite($suiteChild); + } + foreach ($suite->getTests() as $test) { + $tests[] = $this->formatTest($test); + } + + $data = [ + 'id' => $suite->getId(), + 'execution_id' => $suite->getExecution()->getId(), + 'uuid' => $suite->getUuid(), + 'title' => $suite->getTitle(), + 'campaign' => $suite->getCampaign(), + 'file' => $suite->getFile(), + 'duration' => $suite->getDuration(), + 'hasSkipped' => $suite->hasSkipped() ? 1 : 0, + 'hasPending' => $suite->hasPending() ? 1 : 0, + 'hasPasses' => $suite->hasPasses() ? 1 : 0, + 'hasFailures' => $suite->hasFailures() ? 1 : 0, + 'totalSkipped' => $suite->getTotalSkipped(), + 'totalPending' => $suite->getTotalPending(), + 'totalPasses' => $suite->getTotalPasses(), + 'totalFailures' => $suite->getTotalFailures(), + 'hasSuites' => $suite->getHasSuites(), + 'hasTests' => $suite->getHasTests(), + 'parent_id' => $suite->getParentId(), + 'insertion_date' => $suite->getInsertionDate() + ->setTimezone(new \DateTimeZone('-01:00')) + ->format('Y-m-d H:i:s'), + 'suites' => $suites, + 'tests' => $tests, + 'childrenData' => $this->stats[$suite->getId()] ?? [], + ]; + + if ($this->filterEmptyArrays) { + return array_filter($data, function ($value): bool { + return !is_array($value) || !empty($value); + }); + } + + return $data; + } + + /** + * @return array + */ + private function formatTest(Test $test): array + { + $data = [ + 'id' => $test->getId(), + 'suite_id' => $test->getSuite()->getId(), + 'uuid' => $test->getUuid(), + 'identifier' => $test->getIdentifier(), + 'title' => $test->getTitle(), + 'state' => $test->getState(), + 'duration' => $test->getDuration(), + 'error_message' => $test->getErrorMessage(), + 'stack_trace' => $test->getStackTrace(), + 'diff' => $test->getDiff(), + 'insertion_date' => $test->getInsertionDate() + ->setTimezone(new \DateTimeZone('-01:00')) + ->format('Y-m-d H:i:s'), + ]; + + if ($test->getFormattedStackTrace() !== null) { + $data['stack_trace_formatted'] = $test->getFormattedStackTrace(); + } + + return $data; + } + + /** + * @return array> + */ + private function getTests(): array + { + $tests = []; + foreach ($this->suites as $suite) { + foreach ($suite->getTests() as $test) { + if ($test->getState() == 'failed' && $test->getStackTrace()) { + $stackTrace = str_replace(' at', '
    at', htmlentities($test->getStackTrace())); + $test->setFormattedStackTrace($stackTrace); + } + if (!isset($tests[$test->getSuite()->getId()])) { + $tests[$test->getSuite()->getId()] = []; + } + $tests[$test->getSuite()->getId()][$test->getId()] = $test; + } + } + + return $tests; + } + + /** + * @return array + */ + private function buildTree(?int $parentId, bool $isRoot): array + { + $tree = []; + foreach ($this->suites as $suite) { + if ($this->filterSuiteId + && $isRoot + && $suite->getId() !== $this->filterSuiteId) { + continue; + } + if ($suite->getParentId() !== $parentId) { + continue; + } + + if ($suite->getHasTests() == 1 && isset($this->tests[$suite->getId()])) { + $suite->setTests($this->tests[$suite->getId()]); + } + + $suite->setSuites( + $this->buildTree($suite->getId(), false) + ); + + $tree[$suite->getId()] = $suite; + + if ($isRoot) { + $this->stats[$suite->getId()] = [ + 'totalPasses' => $this->countStatus($suite->getTotalPasses(), $suite->getSuites(), 'passes'), + 'totalFailures' => $this->countStatus($suite->getTotalFailures(), $suite->getSuites(), 'failures'), + 'totalPending' => $this->countStatus($suite->getTotalPending(), $suite->getSuites(), 'pending'), + 'totalSkipped' => $this->countStatus($suite->getTotalSkipped(), $suite->getSuites(), 'skipped'), + ]; + + // When the "failed" toggle is turned on + if (in_array('failed', $this->filterStates) && $this->stats[$suite->getId()]['totalFailures'] > 0) { + continue; + } + // When the "pending" toggle is turned on + if (in_array('pending', $this->filterStates) && $this->stats[$suite->getId()]['totalPending'] > 0) { + continue; + } + // When the "skipped" toggle is turned on + if (in_array('skipped', $this->filterStates) && $this->stats[$suite->getId()]['totalSkipped'] > 0) { + continue; + } + // When the "passed" toggle is turned on and we didn't accept this suite, it must only be shown if + // it hasn't any pending or failed test + // this prevents showing a suite with passed and failed test when we hide failed tests for example + if (in_array('passed', $this->filterStates) + && $this->stats[$suite->getId()]['totalPasses'] > 0 + && $this->stats[$suite->getId()]['totalFailures'] == 0 + && $this->stats[$suite->getId()]['totalSkipped'] == 0 + && $this->stats[$suite->getId()]['totalPending'] == 0) { + continue; + } + unset($tree[$suite->getId()]); + } + } + + return $tree; + } + + /** + * @param array $suites + */ + private function countStatus(int $basis, array $suites, string $status): int + { + $num = $basis; + + foreach ($suites as $suite) { + $num += $suite->{'getTotal' . ucfirst($status)}(); + + if ($suite->getHasSuites() == 1) { + $num += $this->countStatus(0, $suite->getSuites(), $status); + } + } + + return $num; + } + + /** + * Filter the whole tree when using fulltext search + * + * @param array $suites + * + * @return array + */ + private function filterTree(array $suites): array + { + foreach ($suites as $key => &$suite) { + $suiteChildren = $suite->getSuites(); + $numSuiteTests = $suite->getTests()->count(); + if (!empty($suiteChildren)) { + $suite->setSuites($this->filterTree($suiteChildren)); + } + if (empty($suiteChildren) + && $numSuiteTests === 0 + && $this->filterSuiteSearch($suite) + ) { + unset($suites[$key]); + } + } + + return array_filter($suites, [$this, 'filterSuiteSearch']); + } + + /** + * Filter each suite with text search in tests + * + * @return bool + */ + private function filterSuiteSearch(Suite $suite): bool + { + if (empty($this->filterSearch)) { + return true; + } + + // Title + if (stripos($suite->getTitle(), $this->filterSearch) !== false) { + return true; + } + // Tests + foreach ($suite->getTests() as $test) { + if (stripos($test->getTitle(), $this->filterSearch) !== false) { + return true; + } + } + + return false; + } +} diff --git a/src/Upgrade/upgrade.php b/src/Upgrade/upgrade.php deleted file mode 100644 index 6abaabb..0000000 --- a/src/Upgrade/upgrade.php +++ /dev/null @@ -1,39 +0,0 @@ -where('name', '=', 'version')->first(); - -echo "Database version:\t " . $version->value . "\n"; -echo "Current version: \t " . QANB_VERSION . "\n"; -if ($version->value >= QANB_VERSION) { - echo "Version up-to-date. Nothing to do here.\n\n"; - exit(0); -} -echo "\n/!\ Upgrade required.\n\n"; - -for ($i = $version->value; $i < QANB_VERSION; ++$i) { - echo "- Upgrading from $i to " . ($i + 1) . "...\n"; - $j = $i + 1; - //we need to execute what's in the ($i+1) folder if it exists - $filename = "$j.php"; - if (file_exists($upgrade_folders_path . $filename)) { - echo "\t- file $filename found, executing...\n"; - $return = include $upgrade_folders_path . $filename; - if (!$return) { - exit("Upgrading to version $j failed.\n"); - } - } - echo "\n"; -} diff --git a/src/Upgrade/versions/2.php b/src/Upgrade/versions/2.php deleted file mode 100644 index 193e0b4..0000000 --- a/src/Upgrade/versions/2.php +++ /dev/null @@ -1,23 +0,0 @@ -where('name', '=', 'version')->update(['value' => 2]); - } catch (Exception $e) { - return false; - } - echo "Finished updating database\n\n"; - - return true; -} - -return update2(); diff --git a/src/Upgrade/versions/3.php b/src/Upgrade/versions/3.php deleted file mode 100644 index c8aace8..0000000 --- a/src/Upgrade/versions/3.php +++ /dev/null @@ -1,32 +0,0 @@ -where('name', '=', 'version')->update(['value' => 3]); - } catch (Exception $e) { - error_log($e->getMessage()); - - return false; - } - echo "Finished updating database\n\n"; - - return true; -} - -return update3(); diff --git a/src/database.php b/src/database.php deleted file mode 100644 index 98d9043..0000000 --- a/src/database.php +++ /dev/null @@ -1,17 +0,0 @@ -addConnection([ - 'driver' => 'mysql', - 'host' => QANB_DB_HOST, - 'database' => QANB_DB_NAME, - 'username' => QANB_DB_USERNAME, - 'password' => QANB_DB_PASSWORD, - 'charset' => 'utf8', - 'collation' => 'utf8_unicode_ci', - 'prefix' => '', -]); -$capsule->setAsGlobal(); -$capsule->bootEloquent(); diff --git a/src/routes.php b/src/routes.php deleted file mode 100644 index f9f8404..0000000 --- a/src/routes.php +++ /dev/null @@ -1,43 +0,0 @@ -get('/', function (Request $request, Response $response) { - return $response; - }); - - //reports routes - $app->group('/reports', function (RouteCollectorProxy $group) { - $group->get('', [ReportController::class, 'index']); - $group->get('/{report:[0-9]+}', [ReportController::class, 'report']); - $group->get('/{report:[0-9]+}/suites/{suite:[0-9]+}', [ReportController::class, 'suite']); - - $group->delete('/{report:[0-9]+}', [ReportController::class, 'delete']); - }); - $app->get('/hook/add', [ReportController::class, 'insert']); - $app->get('/hook/reports/import', [ReportController::class, 'import']); - - //graph routes - $app->group('/graph', function (RouteCollectorProxy $group) { - $group->get('', [GraphController::class, 'index']); - $group->get('/parameters', [GraphController::class, 'parameters']); - }); - - //data routes - $app->get('/data/badge', [DataController::class, 'badge']); - $app->get('/data/badge/svg', [DataController::class, 'svg']); - - // healthcheck - $app->get('/healthcheck', [HealthCheckController::class, 'check']); -} diff --git a/src/settings.php b/src/settings.php deleted file mode 100644 index ecf1a00..0000000 --- a/src/settings.php +++ /dev/null @@ -1,9 +0,0 @@ -request('GET', '/data/badge'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('schemaVersion', $content); + $this->assertEquals('1', $content['schemaVersion']); + $this->assertArrayHasKey('label', $content); + $this->assertEquals('develop', $content['label']); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('100% passed', $content['message']); + $this->assertArrayHasKey('color', $content); + $this->assertEquals('green', $content['color']); + } + + public function testBadgeJsonNotFound(): void + { + $client = static::createClient(); + $client->request('GET', '/data/badge?branch=1.6'); + $response = $client->getResponse(); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Execution not found', $content['message']); + } + + public function testBadgeSvg(): void + { + $client = static::createClient(); + $client->request('GET', '/data/badge/svg'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('image/svg+xml', $response->headers->get('content-type')); + + $content = $response->getContent(); + $this->assertStringContainsString('develop', $content); + } + + public function testBadgeSvgNotFound(): void + { + $client = static::createClient(); + $client->request('GET', '/data/badge/svg?branch=1.6'); + $response = $client->getResponse(); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type')); + + $content = $response->getContent(); + $this->assertEquals('Execution not found', $content); + } +} diff --git a/tests/Controller/GraphControllerTest.php b/tests/Controller/GraphControllerTest.php new file mode 100644 index 0000000..5d7a73e --- /dev/null +++ b/tests/Controller/GraphControllerTest.php @@ -0,0 +1,84 @@ +request('GET', '/graph?start_date=2023-11-01'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = json_decode($response->getContent(), true); + $this->assertGreaterThan(0, count($content)); + foreach ($content as $item) { + $this->assertArrayHasKey('id', $item); + $this->assertIsInt($item['id']); + $this->assertArrayHasKey('start_date', $item); + $this->assertArrayHasKey('end_date', $item); + $this->assertArrayHasKey('version', $item); + $this->assertEquals('develop', $item['version']); + $this->assertArrayHasKey('suites', $item); + $this->assertIsInt($item['suites']); + $this->assertArrayHasKey('tests', $item); + $this->assertIsInt($item['tests']); + $this->assertArrayHasKey('skipped', $item); + $this->assertIsInt($item['skipped']); + $this->assertArrayHasKey('passes', $item); + $this->assertIsInt($item['passes']); + $this->assertArrayHasKey('failures', $item); + $this->assertIsInt($item['failures']); + $this->assertArrayHasKey('pending', $item); + $this->assertIsInt($item['pending']); + } + } + + public function testParameters(): void + { + $client = static::createClient(); + $client->request('GET', '/graph/parameters'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = json_decode($response->getContent(), true); + $this->assertArrayHasKey('periods', $content); + $this->assertIsArray($content['periods']); + $this->assertArrayHasKey('type', $content['periods']); + $this->assertEquals('select', $content['periods']['type']); + $this->assertArrayHasKey('name', $content['periods']); + $this->assertEquals('period', $content['periods']['name']); + $this->assertArrayHasKey('values', $content['periods']); + $this->assertIsArray($content['periods']['values']); + $this->assertEquals('Last 30 days', $content['periods']['values'][0]['name']); + $this->assertEquals('last_month', $content['periods']['values'][0]['value']); + $this->assertEquals('Last 60 days', $content['periods']['values'][1]['name']); + $this->assertEquals('last_two_months', $content['periods']['values'][1]['value']); + $this->assertEquals('Last 12 months', $content['periods']['values'][2]['name']); + $this->assertEquals('last_year', $content['periods']['values'][2]['value']); + $this->assertArrayHasKey('default', $content['periods']); + $this->assertEquals('last_month', $content['periods']['default']); + + $this->assertArrayHasKey('versions', $content); + $this->assertIsArray($content['versions']); + $this->assertArrayHasKey('type', $content['versions']); + $this->assertEquals('select', $content['versions']['type']); + $this->assertArrayHasKey('name', $content['versions']); + $this->assertEquals('version', $content['versions']['name']); + $this->assertArrayHasKey('values', $content['versions']); + $this->assertIsArray($content['versions']['values']); + $this->assertEquals('Develop', $content['versions']['values'][0]['name']); + $this->assertEquals('develop', $content['versions']['values'][0]['value']); + $this->assertArrayHasKey('default', $content['versions']); + $this->assertEquals('develop', $content['versions']['default']); + } +} diff --git a/tests/Controller/HealthCheckControllerTest.php b/tests/Controller/HealthCheckControllerTest.php new file mode 100644 index 0000000..c3b2a43 --- /dev/null +++ b/tests/Controller/HealthCheckControllerTest.php @@ -0,0 +1,25 @@ +request('GET', '/healthcheck'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = json_decode($response->getContent(), true); + $this->assertArrayHasKey('database', $content); + $this->assertEquals(true, $content['database']); + $this->assertArrayHasKey('gcp', $content); + $this->assertEquals(true, $content['gcp']); + } +} diff --git a/tests/Controller/ImportControllerTest.php b/tests/Controller/ImportControllerTest.php new file mode 100644 index 0000000..3a3ace3 --- /dev/null +++ b/tests/Controller/ImportControllerTest.php @@ -0,0 +1,300 @@ +request('GET', '/hook/add'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testOldReportWithParameterToken(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testOldReportWithParameterFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=2023-01-01-develop.json'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testOldReportWithParameterFilenameAndBakToken(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=2023-01-01-develop.json&token=BAD'); + $response = $client->getResponse(); + + $this->assertEquals(401, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Invalid token', $content['message']); + } + + public function testOldReportWithNoVersionInFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=2023-01-01.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Could not retrieve version from filename', $content['message']); + } + + public function testOldReportWithBadVersionInFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=2023-01-01-.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Version found not correct () from filename 2023-01-01-.json', $content['message']); + } + + public function testOldReportWithNotExistingFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=2023-01-01-truc.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Unable to retrieve content from GCP URL', $content['message']); + } + + public function testOldReportOk(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=autoupgrade_2024-01-01-develop.json&token=AZERTY&campaign=autoupgrade&platform=cli'); + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('status', $content); + $this->assertEquals('ok', $content['status']); + $this->assertArrayHasKey('report', $content); + $this->assertIsInt($content['report']); + } + + public function testOldReportAlreadyExisting(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/add?filename=autoupgrade_2024-01-01-develop.json&token=AZERTY&campaign=autoupgrade&platform=cli'); + $response = $client->getResponse(); + + $this->assertEquals(403, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('A similar entry was found (criteria: version develop, platform cli, campaign autoupgrade, date 2024-01-01).', $content['message']); + } + + public function testReportWithNoParameters(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testReportWithParameterToken(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testReportWithParameterFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2023-01-01-develop.json'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('No enough parameters', $content['message']); + } + + public function testReportWithParameterFilenameAndBakToken(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2023-01-01-develop.json&token=BAD'); + $response = $client->getResponse(); + + $this->assertEquals(401, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Invalid token', $content['message']); + } + + public function testReportWithNoVersionInFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2023-01-01.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Could not retrieve version from filename', $content['message']); + } + + public function testReportWithBadVersionInFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2023-01-01-.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Version found not correct () from filename 2023-01-01-.json', $content['message']); + } + + public function testReportWithNotExistingFilename(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2023-01-01-truc.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Unable to retrieve content from GCP URL', $content['message']); + } + + public function testReportOk(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2024-01-01-develop.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('status', $content); + $this->assertEquals('ok', $content['status']); + $this->assertArrayHasKey('report', $content); + $this->assertIsInt($content['report']); + } + + public function testReportAlreadyExisting(): void + { + $client = static::createClient(); + $client->request('GET', '/hook/reports/import?filename=2024-01-01-develop.json&token=AZERTY'); + $response = $client->getResponse(); + + $this->assertEquals(403, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('A similar entry was found (criteria: version develop, platform chromium, campaign functional, date 2024-01-01).', $content['message']); + } +} diff --git a/tests/Controller/IndexControllerTest.php b/tests/Controller/IndexControllerTest.php new file mode 100644 index 0000000..abcd2b6 --- /dev/null +++ b/tests/Controller/IndexControllerTest.php @@ -0,0 +1,23 @@ +request('GET', '/'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertEquals([], $content); + } +} diff --git a/tests/Controller/ReportControllerTest.php b/tests/Controller/ReportControllerTest.php new file mode 100644 index 0000000..233cf2b --- /dev/null +++ b/tests/Controller/ReportControllerTest.php @@ -0,0 +1,414 @@ +request('GET', '/reports'); + $response = $client->getResponse(); + + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = json_decode($response->getContent(), true); + $this->assertGreaterThan(0, count($content)); + $datePrevious = null; + foreach ($content as $item) { + if ($datePrevious) { + $this->assertGreaterThanOrEqual($item['start_date'], $datePrevious); + } + $datePrevious = $item['start_date']; + $this->assertArrayHasKey('id', $item); + $this->assertIsInt($item['id']); + $this->assertArrayHasKey('date', $item); + $this->assertArrayHasKey('version', $item); + $this->assertArrayHasKey('campaign', $item); + $this->assertContains($item['campaign'], ReportImporter::FILTER_CAMPAIGNS); + $this->assertArrayHasKey('browser', $item); + $this->assertContains($item['browser'], ReportImporter::FILTER_PLATFORMS); + $this->assertArrayHasKey('platform', $item); + $this->assertContains($item['platform'], ReportImporter::FILTER_PLATFORMS); + $this->assertEquals($item['browser'], $item['platform']); + $this->assertArrayHasKey('start_date', $item); + $this->assertArrayHasKey('end_date', $item); + $this->assertArrayHasKey('duration', $item); + $this->assertIsInt($item['duration']); + $this->assertArrayHasKey('suites', $item); + $this->assertArrayHasKey('tests', $item); + $this->assertIsArray($item['tests']); + $this->assertArrayHasKey('total', $item['tests']); + $this->assertArrayHasKey('passed', $item['tests']); + $this->assertArrayHasKey('failed', $item['tests']); + $this->assertArrayHasKey('pending', $item['tests']); + $this->assertArrayHasKey('skipped', $item['tests']); + $this->assertArrayHasKey('broken_since_last', $item); + $this->assertArrayHasKey('fixed_since_last', $item); + $this->assertArrayHasKey('equal_since_last', $item); + $this->assertArrayHasKey('download', $item); + $this->assertArrayHasKey('xml', $item); + } + } + + public function testReportNotFound(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/1234567890'); + $response = $client->getResponse(); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + $this->assertArrayHasKey('message', $content); + $this->assertEquals('Execution not found', $content['message']); + } + + public function testReportID(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/2'); + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + + $this->assertArrayHasKey('id', $content); + $this->assertIsInt($content['id']); + $this->assertArrayHasKey('date', $content); + $this->assertArrayHasKey('version', $content); + $this->assertArrayHasKey('campaign', $content); + $this->assertContains($content['campaign'], ReportImporter::FILTER_CAMPAIGNS); + $this->assertArrayHasKey('browser', $content); + $this->assertContains($content['browser'], ReportImporter::FILTER_PLATFORMS); + $this->assertArrayHasKey('platform', $content); + $this->assertContains($content['platform'], ReportImporter::FILTER_PLATFORMS); + $this->assertEquals($content['browser'], $content['platform']); + $this->assertArrayHasKey('start_date', $content); + $this->assertArrayHasKey('end_date', $content); + $this->assertArrayHasKey('duration', $content); + $this->assertIsInt($content['duration']); + $this->assertArrayHasKey('suites', $content); + $this->assertIsInt($content['tests']); + $this->assertArrayHasKey('tests', $content); + $this->assertIsInt($content['tests']); + $this->assertArrayHasKey('broken_since_last', $content); + $this->assertArrayHasKey('fixed_since_last', $content); + $this->assertArrayHasKey('equal_since_last', $content); + $this->assertArrayHasKey('skipped', $content); + $this->assertIsInt($content['skipped']); + $this->assertArrayHasKey('pending', $content); + $this->assertIsInt($content['pending']); + $this->assertArrayHasKey('passes', $content); + $this->assertIsInt($content['passes']); + $this->assertArrayHasKey('failures', $content); + $this->assertIsInt($content['failures']); + + $this->assertArrayHasKey('suites_data', $content); + $this->assertIsArray($content['suites_data']); + foreach ($content['suites_data'] as $suiteId => $suiteItem) { + $this->partialTestSuite($content['id'], $suiteId, $suiteItem, null, true); + } + } + + public function testReportIDSuiteID(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/2/suites/4'); + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->headers->has('content-type')); + $this->assertEquals('application/json', $response->headers->get('content-type')); + + $content = $response->getContent(); + $content = json_decode($content, true); + + $this->partialTestSuite(2, 4, $content, null, false); + } + + public function testCompareReport(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/2'); + $response = $client->getResponse(); + $content = $response->getContent(); + $content = json_decode($content, true); + + $data = \file_get_contents('https://api-nightly.prestashop-project.org/reports/' . self::$reportId); + $data = json_decode($data, true); + + $this->partialCompare($data, $content); + } + + public function testCompareReportFilterText(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/2?search=currency'); + $response = $client->getResponse(); + $content = $response->getContent(); + $content = json_decode($content, true); + + $data = \file_get_contents('https://api-nightly.prestashop-project.org/reports/' . self::$reportId . '?search=currency'); + $data = json_decode($data, true); + + $this->partialCompare($data, $content); + } + + public function testCompareReportFilterState(): void + { + $states = [ + 'failed', + 'pending', + 'skipped', + 'passed', + ]; + $client = static::createClient(); + + foreach ($states as $stateRemoved) { + $query = []; + foreach ($states as $state) { + if ($state === $stateRemoved) { + continue; + } + $query[] = 'filter_state[]=' . $state; + } + + $client->request('GET', '/reports/2?' . implode('&', $query)); + $response = $client->getResponse(); + $content = $response->getContent(); + $content = json_decode($content, true); + + $data = \file_get_contents('https://api-nightly.prestashop-project.org/reports/' . self::$reportId . '?' . implode('&', $query)); + $data = json_decode($data, true); + + $this->partialCompare($data, $content); + } + } + + public function testCompareSuite(): void + { + $client = static::createClient(); + $client->request('GET', '/reports/2/suites/4'); + $response = $client->getResponse(); + $content = $response->getContent(); + $content = json_decode($content, true); + + $data = \file_get_contents('https://api-nightly.prestashop-project.org/reports/' . self::$reportId . '/suites/' . self::$suiteId); + $data = json_decode($data, true); + + $this->partialCompareSuite($data, $content); + } + + /** + * @param array> $expected + * @param array> $actual + */ + private function partialCompare(array $expected, array $actual): void + { + foreach ($expected as $expectedKey => $expectedValue) { + if (in_array($expectedKey, [ + 'id', + 'start_date', + 'end_date', + ])) { + continue; + } + if ($expectedKey == 'suites_data') { + $expectedArrayKeys = array_keys($expected['suites_data']); + $actualArrayKeys = array_keys($actual['suites_data']); + $this->assertEquals(count($expectedArrayKeys), count($actualArrayKeys)); + foreach ($expectedArrayKeys as $key => $value) { + // @phpstan-ignore-next-line + $this->partialCompareSuite($expected['suites_data'][$value], $actual['suites_data'][$actualArrayKeys[$key]]); + } + continue; + } + $this->assertEquals($expectedValue, $actual[$expectedKey], 'Key Root : ' . $expectedKey); + } + } + + /** + * @param array> $expected + * @param array> $actual + */ + private function partialCompareSuite(array $expected, array $actual): void + { + foreach ($expected as $expectedKey => $expectedValue) { + $actualValue = $actual[$expectedKey]; + if (in_array($expectedKey, [ + 'id', + 'execution_id', + 'insertion_date', + 'parent_id', + ])) { + continue; + } + if ($expectedKey == 'tests') { + $this->assertEquals(count($expectedValue), count($actualValue)); + foreach ($expectedValue as $key => $expectedItemValue) { + // @phpstan-ignore-next-line + $this->partialCompareTest($expectedItemValue, $actualValue[$key]); + } + continue; + } + if ($expectedKey == 'suites') { + $expectedArrayKeys = array_keys($expectedValue); + $actualArrayKeys = array_keys($actualValue); + $this->assertEquals(count($expectedArrayKeys), count($actualArrayKeys)); + foreach ($expectedArrayKeys as $key => $value) { + // @phpstan-ignore-next-line + $this->partialCompareSuite($expectedValue[$value], $actualValue[$actualArrayKeys[$key]]); + } + continue; + } + $this->assertEquals($expectedValue, $actualValue, 'Key Suite : ' . $expectedKey); + } + } + + /** + * @param array $expected + * @param array $actual + */ + private function partialCompareTest(array $expected, array $actual): void + { + foreach ($expected as $expectedKey => $expectedValue) { + $actualValue = $actual[$expectedKey]; + if (in_array($expectedKey, [ + 'id', + 'suite_id', + 'insertion_date', + ])) { + continue; + } + $this->assertEquals($expectedValue, $actualValue, 'Key Test: ' . $expectedKey); + } + } + + /** + * @param array $item + */ + private function partialTestSuite(int $executionId, int $id, array $item, int $idParent = null, bool $hasChildrenData = null): void + { + $this->assertIsInt($id); + + $this->assertArrayHasKey('id', $item); + $this->assertIsInt($item['id']); + $this->assertEquals($item['id'], $id); + $this->assertArrayHasKey('execution_id', $item); + $this->assertEquals($item['execution_id'], $executionId); + $this->assertArrayHasKey('uuid', $item); + $this->assertArrayHasKey('title', $item); + $this->assertArrayHasKey('campaign', $item); + $this->assertArrayHasKey('file', $item); + $this->assertArrayHasKey('duration', $item); + $this->assertArrayHasKey('hasSkipped', $item); + $this->assertIsInt($item['hasSkipped']); + $this->assertArrayHasKey('hasPending', $item); + $this->assertIsInt($item['hasPending']); + $this->assertArrayHasKey('hasPasses', $item); + $this->assertIsInt($item['hasPasses']); + $this->assertArrayHasKey('hasFailures', $item); + $this->assertIsInt($item['hasFailures']); + $this->assertArrayHasKey('totalSkipped', $item); + $this->assertIsInt($item['totalSkipped']); + $this->assertArrayHasKey('totalPending', $item); + $this->assertIsInt($item['totalPending']); + $this->assertArrayHasKey('totalPasses', $item); + $this->assertIsInt($item['totalPasses']); + $this->assertArrayHasKey('totalFailures', $item); + $this->assertIsInt($item['totalFailures']); + $this->assertArrayHasKey('hasSuites', $item); + $this->assertIsInt($item['hasSuites']); + $this->assertArrayHasKey('hasTests', $item); + $this->assertIsInt($item['hasTests']); + $this->assertArrayHasKey('parent_id', $item); + if (!$idParent) { + $this->assertEquals($item['parent_id'], $idParent); + } + $this->assertArrayHasKey('insertion_date', $item); + + if ($item['hasSuites']) { + $this->assertArrayHasKey('suites', $item); + $this->assertIsArray($item['suites']); + $this->assertGreaterThan(0, count($item['suites'])); + foreach ($item['suites'] as $suiteChildId => $suiteChild) { + $this->assertIsInt($suiteChildId); + $this->partialTestSuite($executionId, $suiteChildId, $suiteChild, $id); + } + } + if ($item['hasTests']) { + $this->assertArrayHasKey('tests', $item); + $this->assertIsArray($item['tests']); + $this->assertGreaterThan(0, count($item['tests'])); + foreach ($item['tests'] as $testItem) { + $this->partialTestTest($item['id'], $testItem); + } + } + + if (is_bool($hasChildrenData) && $hasChildrenData) { + $this->assertArrayHasKey('childrenData', $item); + $this->assertIsArray($item['childrenData']); + $this->assertArrayHasKey('totalPasses', $item['childrenData']); + $this->assertIsInt($item['childrenData']['totalPasses']); + $this->assertGreaterThanOrEqual($item['totalPasses'], $item['childrenData']['totalPasses']); + $this->assertArrayHasKey('totalFailures', $item['childrenData']); + $this->assertIsInt($item['childrenData']['totalFailures']); + $this->assertGreaterThanOrEqual($item['totalFailures'], $item['childrenData']['totalFailures']); + $this->assertArrayHasKey('totalPending', $item['childrenData']); + $this->assertIsInt($item['childrenData']['totalPending']); + $this->assertGreaterThanOrEqual($item['totalPending'], $item['childrenData']['totalPending']); + $this->assertArrayHasKey('totalSkipped', $item['childrenData']); + $this->assertIsInt($item['childrenData']['totalSkipped']); + $this->assertGreaterThanOrEqual($item['totalSkipped'], $item['childrenData']['totalSkipped']); + } else { + $this->assertArrayNotHasKey('childrenData', $item); + } + } + + /** + * @param array $test + */ + private function partialTestTest(int $suiteId, array $test): void + { + $this->assertArrayHasKey('id', $test); + $this->assertIsInt($test['id']); + $this->assertArrayHasKey('suite_id', $test); + $this->assertEquals($test['suite_id'], $suiteId); + $this->assertArrayHasKey('uuid', $test); + $this->assertArrayHasKey('identifier', $test); + $this->assertArrayHasKey('title', $test); + $this->assertArrayHasKey('state', $test); + $this->assertArrayHasKey('duration', $test); + $this->assertArrayHasKey('error_message', $test); + $this->assertArrayHasKey('stack_trace', $test); + $this->assertArrayHasKey('diff', $test); + $this->assertArrayHasKey('insertion_date', $test); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..1e75e32 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,15 @@ +bootEnv(dirname(__DIR__) . '/.env'); +} + +if ($_SERVER['APP_DEBUG']) { + umask(0000); +}