diff --git a/.docker/nginx.conf b/.docker/nginx.conf index 43dbd195..8fe03dbc 100644 --- a/.docker/nginx.conf +++ b/.docker/nginx.conf @@ -1,13 +1,12 @@ worker_processes auto; -error_log /var/log/nginx/error.log notice; +error_log /dev/stderr notice; pid /tmp/nginx.pid; events { worker_connections 1024; } - http { proxy_temp_path /tmp/proxy_temp; client_body_temp_path /tmp/client_temp; @@ -18,7 +17,7 @@ http { include /etc/nginx/mime.types; default_type application/octet-stream; - set_real_ip_from 172.16.0.0/8; + set_real_ip_from 172.16.0.0/16; real_ip_recursive on; real_ip_header X-Forwarded-For; @@ -26,11 +25,9 @@ http { '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; + access_log /dev/stdout main; sendfile on; - #tcp_nopush on; - keepalive_timeout 65; gzip on; diff --git a/.docker/templates/default.conf.template b/.docker/templates/default.conf.template new file mode 100644 index 00000000..61c4e648 --- /dev/null +++ b/.docker/templates/default.conf.template @@ -0,0 +1,47 @@ +server { + listen ${NGINX_PORT}; + server_name localhost; + + root ${NGINX_WEB_ROOT}; + + client_max_body_size ${NGINX_MAX_BODY_SIZE}; + + # This also needs to be set in the single server tag and not only in http. + set_real_ip_from 172.16.0.0/16; + real_ip_recursive on; + real_ip_header X-Forwarded-For; + + location / { + # try to serve file directly, fallback to index.php + try_files $uri /index.php$is_args$args; + } + + # Protect files and directories from prying eyes. + location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|.tar|.gz|.bz2|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ { + deny all; + return 404; + } + + location ~ ^/index\.php(/|$) { + fastcgi_buffers 16 32k; + fastcgi_buffer_size 64k; + fastcgi_busy_buffers_size 64k; + + fastcgi_pass ${NGINX_FPM_SERVICE}; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + + internal; + } + + location ~ \.php$ { + return 404; + } + + # Send log message to files symlinked to stdout/stderr. + error_log /dev/stderr; + access_log /dev/stdout main; +} diff --git a/.docker/vhost.conf b/.docker/vhost.conf deleted file mode 100644 index b50231d4..00000000 --- a/.docker/vhost.conf +++ /dev/null @@ -1,33 +0,0 @@ -server { - listen 8080; - server_name localhost; - root /app/public; - - location / { - # try to serve file directly, fallback to index.php - try_files $uri /index.php$is_args$args; - } - - location ~ ^/index\.php(/|$) { - fastcgi_buffers 16 32k; - fastcgi_buffer_size 64k; - fastcgi_busy_buffers_size 64k; - - fastcgi_pass phpfpm:9000; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - - internal; - } - - location ~ \.php$ { - return 404; - } - - # Send log message to files symlinked to stdout/stderr. - error_log /dev/stderr; - access_log /dev/stdout main; -} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..18e4bd89 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://editorconfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 4 + +[*.{css,js,twig}] +indent_size = 2 diff --git a/.env b/.env index ed844e0d..395355e1 100644 --- a/.env +++ b/.env @@ -5,6 +5,7 @@ ###> aakb/itkdev-docker configuration ### COMPOSE_PROJECT_NAME=itstyr COMPOSE_DOMAIN=itstyr.local.itkdev.dk +ITKDEV_TEMPLATE=symfony-6 ###< aakb/itkdev-docker configuration ### ###> symfony/framework-bundle ### diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..b20ca094 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,23 @@ +#### Link to ticket + +Please add a link to the ticket being addressed by this change. + +#### Description + +Please include a short description of the suggested change and the reasoning behind the approach you have chosen. + +#### Screenshot of the result + +If your change affects the user interface you should include a screenshot of the result with the pull request. + +#### Checklist + +- [ ] My code passes our static analysis suite. +- [ ] My code passes our continuous integration process. + +If your code does not pass all the requirements on the checklist you have to add a comment explaining why this change +should be exempt from the list. + +#### Additional comments or questions + +If you have any further comments or questions for the reviewer please add them here. diff --git a/.github/workflows/changelog.yaml b/.github/workflows/changelog.yaml new file mode 100644 index 00000000..483da6e9 --- /dev/null +++ b/.github/workflows/changelog.yaml @@ -0,0 +1,29 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/changelog.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Changelog +### +### Checks that changelog has been updated + +name: Changelog + +on: + pull_request: + +jobs: + changelog: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Git fetch + run: git fetch + + - name: Check that changelog has been updated. + run: git diff --exit-code origin/${{ github.base_ref }} -- CHANGELOG.md && exit 1 || exit 0 diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml new file mode 100644 index 00000000..fe133512 --- /dev/null +++ b/.github/workflows/composer.yaml @@ -0,0 +1,68 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/composer.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Composer +### +### Validates composer.json and checks that it's normalized. +### +### #### Assumptions +### +### 1. A docker compose service named `phpfpm` can be run and `composer` can be +### run inside the `phpfpm` service. +### 2. [ergebnis/composer-normalize](https://github.com/ergebnis/composer-normalize) +### is a dev requirement in `composer.json`: +### +### ``` shell +### docker compose run --rm phpfpm composer require --dev ergebnis/composer-normalize +### ``` +### +### Normalize `composer.json` by running +### +### ``` shell +### docker compose run --rm phpfpm composer normalize +### ``` + +name: Composer + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + composer-validate: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + - run: | + docker network create frontend + docker compose run --rm phpfpm composer validate --strict + + composer-normalized: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + - run: | + docker network create frontend + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm composer normalize --dry-run + + composer-audit: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + - run: | + docker network create frontend + docker compose run --rm phpfpm composer audit diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml new file mode 100644 index 00000000..5b20c8da --- /dev/null +++ b/.github/workflows/javascript.yaml @@ -0,0 +1,36 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/symfony/javascript.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Symfony JavaScript (and TypeScript) +### +### Validates JavaScript files. +### +### #### Assumptions +### +### 1. A docker compose service named `prettier` for running +### [Prettier](https://prettier.io/) exists. + +name: JavaScript + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + javascript-lint: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - run: | + docker network create frontend + + - run: | + docker compose run --rm prettier 'assets/**/*.js' --check diff --git a/.github/workflows/markdown.yaml b/.github/workflows/markdown.yaml new file mode 100644 index 00000000..60fc0ee5 --- /dev/null +++ b/.github/workflows/markdown.yaml @@ -0,0 +1,43 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/markdown.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Markdown +### +### Lints Markdown files (`**/*.md`) in the project. +### +### [markdownlint-cli configuration +### files](https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#configuration), +### `.markdownlint.jsonc` and `.markdownlintignore`, control what is actually +### linted and how. +### +### #### Assumptions +### +### 1. A docker compose service named `markdownlint` for running `markdownlint` +### (from +### [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli)) +### exists. + +name: Markdown + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + markdown-lint: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - run: | + docker network create frontend + + - run: | + docker compose run --rm markdownlint markdownlint '**/*.md' diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml new file mode 100644 index 00000000..60fb70eb --- /dev/null +++ b/.github/workflows/php.yaml @@ -0,0 +1,56 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/symfony/php.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Symfony PHP +### +### Checks that PHP code adheres to the [Symfony coding +### standards](https://symfony.com/doc/current/contributing/code/standards.html). +### +### #### Assumptions +### +### 1. A docker compose service named `phpfpm` can be run and `composer` can be +### run inside the `phpfpm` service. 2. +### [friendsofphp/php-cs-fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) +### is a dev requirement in `composer.json`: +### +### ``` shell +### docker compose run --rm phpfpm composer require --dev friendsofphp/php-cs-fixer +### ``` +### +### Clean up and check code by running +### +### ``` shell +### docker compose run --rm phpfpm vendor/bin/php-cs-fixer fix +### docker compose run --rm phpfpm vendor/bin/php-cs-fixer fix --dry-run --diff +### ``` +### +### > [!NOTE] The template adds `.php-cs-fixer.dist.php` as [a configuration +### > file for PHP CS +### > Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/config.rst) +### > and this makes it possible to override the actual configuration used in a +### > project by adding a more important configuration file, `.php-cs-fixer.php`. + +name: Symfony PHP + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + coding-standards: + name: PHP - Check Coding Standards + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + docker network create frontend + docker compose run --rm phpfpm composer install + # https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/usage.rst#the-check-command + docker compose run --rm phpfpm vendor/bin/php-cs-fixer fix --dry-run --diff diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 00000000..2cd8700c --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,148 @@ +on: pull_request +name: Review +jobs: + test-composer-install: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + php: [ '8.3' ] + name: Validate composer (${{ matrix.php}}) + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php}} + extensions: http, ctype, iconv + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ matrix.dependency-version }}- + restore-keys: ${{ runner.os }}-composer-${{ matrix.dependency-version }}- + + - name: Validate composer files + run: composer validate composer.json --strict + + - name: Composer install with exported .env variables + run: | + set -a && source .env && set +a + APP_ENV=prod composer install --no-dev -o + +# test-suite: +# name: Test suite (${{ matrix.php }}) +# runs-on: ubuntu-24.04 +# strategy: +# fail-fast: false +# matrix: +# php: [ '8.3' ] +# steps: +# - uses: actions/checkout@v4 +# +# - name: Setup PHP, with composer and extensions +# uses: shivammathur/setup-php@v2 +# with: +# php-version: ${{ matrix.php}} +# extensions: http, ctype, iconv +# coverage: xdebug +# +# - name: Get composer cache directory +# id: composer-cache +# run: echo "::set-output name=dir::$(composer config cache-files-dir)" +# +# - name: Cache dependencies +# uses: actions/cache@v4 +# with: +# path: ${{ steps.composer-cache.outputs.dir }} +# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ matrix.dependency-version }}- +# restore-keys: ${{ runner.os }}-composer-${{ matrix.dependency-version }}- +# +# - name: Install Dependencies +# run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist +# +# - name: Test suite +# run: ./vendor/bin/phpunit --coverage-clover=coverage/unit.xml +# +# - name: Upload coverage to Codecov test +# uses: codecov/codecov-action@v2 +# with: +# files: ./coverage/unit.xml +# flags: unittests, ${{ matrix.php }} + + php-cs-fixer: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + php: ["8.3"] + name: PHP Coding Standards Fixer (PHP ${{ matrix.php }}) + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php}} + extensions: http, ctype, iconv + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ matrix.php }}-composer- + + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist + + - name: php-cs-fixer + run: phpdbg -qrr ./vendor/bin/php-cs-fixer fix --dry-run + + static-analysis: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + php: ['8.3'] + name: Static analysis (${{ matrix.php}}) + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php}} + extensions: http, ctype, iconv + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ matrix.dependency-version }}- + restore-keys: ${{ runner.os }}-composer-${{ matrix.dependency-version }}- + + - name: Install Dependencies + run: | + composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist + bin/console cache:clear + - name: Psalm + run: composer run coding-standards-analysis diff --git a/.github/workflows/styles.yaml b/.github/workflows/styles.yaml new file mode 100644 index 00000000..edc79602 --- /dev/null +++ b/.github/workflows/styles.yaml @@ -0,0 +1,36 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/symfony/styles.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Symfony Styles (CSS and SCSS) +### +### Validates styles files. +### +### #### Assumptions +### +### 1. A docker compose service named `prettier` for running +### [Prettier](https://prettier.io/) exists. + +name: Styles + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + styles-lint: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - run: | + docker network create frontend + + - run: | + docker compose run --rm prettier 'assets/**/*.{css,scss}' --check diff --git a/.github/workflows/twig.yaml b/.github/workflows/twig.yaml new file mode 100644 index 00000000..9b0e3431 --- /dev/null +++ b/.github/workflows/twig.yaml @@ -0,0 +1,48 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/twig.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Twig +### +### Validates Twig files +### +### #### Assumptions +### +### 1. A docker compose service named `phpfpm` can be run and `composer` can be +### run inside the `phpfpm` service. +### 2. [vincentlanglet/twig-cs-fixer](https://github.com/VincentLanglet/Twig-CS-Fixer) +### is a dev requirement in `composer.json`: +### +### ``` shell +### docker compose run --rm phpfpm composer require --dev vincentlanglet/twig-cs-fixer +### ``` +### +### 3. A [Configuration +### file](https://github.com/VincentLanglet/Twig-CS-Fixer/blob/main/docs/configuration.md#configuration-file) +### in the root of the project defines which files to check and rules to use. + +name: Twig + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + twig-lint: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - run: | + docker network create frontend + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm vendor/bin/twig-cs-fixer lint diff --git a/.gitignore b/.gitignore index 5df0eef5..6b6fbbc9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,20 @@ ###> friendsofphp/php-cs-fixer ### /.php-cs-fixer.php /.php-cs-fixer.cache +/.php-cs-fixer.dist.php ###< friendsofphp/php-cs-fixer ### + +###> phpstan/phpstan ### +phpstan.neon +###< phpstan/phpstan ### + +###> symfony/asset-mapper ### +/public/assets/ +/assets/vendor/ +###< symfony/asset-mapper ### + +### phpactor ### +/.phpactor.json +###> vincentlanglet/twig-cs-fixer ### +/.twig-cs-fixer.cache +###< vincentlanglet/twig-cs-fixer ### diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 00000000..02530965 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,22 @@ +// This file is copied from config/markdown/.markdownlint.jsonc in https://github.com/itk-dev/devops_itkdev-docker. +// Feel free to edit the file, but consider making a pull request if you find a general issue with the file. + +// markdownlint-cli configuration file (cf. https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#configuration) +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + }, + // https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections#creating-a-collapsed-section + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md033.md + "no-inline-html": { + "allowed_elements": ["details", "summary"] + } +} diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000..fe1b7feb --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,16 @@ +# This file is copied from config/markdown/.markdownlintignore in https://github.com/itk-dev/devops_itkdev-docker. +# Feel free to edit the file, but consider making a pull request if you find a general issue with the file. + +# https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#ignoring-files +vendor/ +node_modules/ +LICENSE.md +# Drupal +web/*.md +web/core/ +web/libraries/ +web/*/contrib/ + +# Project ignores +mappings.md +templates/svg/font-awesome-info.md diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index ebceb785..ca0693b2 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,18 +1,23 @@ in(__DIR__) - ->exclude(['var', 'vendor', 'node_modules']) +// https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/config.rst -; +$finder = new PhpCsFixer\Finder(); +// Check all files … +$finder->in(__DIR__); +// … that are not ignored by VCS +$finder->ignoreVCSIgnored(true); -return (new PhpCsFixer\Config()) - ->setRules([ - '@Symfony' => true, - 'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'], - // @see https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/rules/import/ordered_imports.rst - 'ordered_imports' => ['imports_order' => ['const', 'class', 'function']], - ]) +$config = new PhpCsFixer\Config(); +$config->setFinder($finder); - ->setFinder($finder) -; +$config->setRules([ + '@Symfony' => true, + 'phpdoc_align' => false, + // Don't remove @param that define collection and array generics (yes they should have complete comments, but). + 'no_superfluous_phpdoc_tags' => false, +]); + +return $config; diff --git a/.twig-cs-fixer.dist.php b/.twig-cs-fixer.dist.php new file mode 100644 index 00000000..82425550 --- /dev/null +++ b/.twig-cs-fixer.dist.php @@ -0,0 +1,16 @@ +in(__DIR__); +// … that are not ignored by VCS +$finder->ignoreVCSIgnored(true); + +$config = new TwigCsFixer\Config\Config(); +$config->setFinder($finder); + +return $config; diff --git a/.woodpecker/stg.yml b/.woodpecker/stg.yml new file mode 100644 index 00000000..d54c53f4 --- /dev/null +++ b/.woodpecker/stg.yml @@ -0,0 +1,34 @@ +when: + - branch: release/* + event: push + +skip_clone: true + +steps: + - name: Run test site update + image: itkdev/ansible-plugin:1 + when: + branch: release/* + event: push + pull: true + settings: + id: + from_secret: id + secret: + from_secret: secret + host: + from_secret: stg_host + path: + from_secret: stg_path + user: + from_secret: user + actions: + - git reset --hard + - git fetch origin ${CI_COMMIT_BRANCH} + - git checkout ${CI_COMMIT_BRANCH} + - git pull + - itkdev-docker-compose-server up --detach --force-recreate + - itkdev-docker-compose-server exec phpfpm composer install --no-dev --classmap-authoritative + # https://symfony.com/doc/current/frontend/asset_mapper.html#serving-assets-in-dev-vs-prod + - itkdev-docker-compose-server exec phpfpm bin/console asset-map:compile + - itkdev-docker-compose-server exec phpfpm bin/console cache:clear diff --git a/CHANGELOG.md b/CHANGELOG.md index 61cabc6f..0769603f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,41 @@ -# ITStyr CHANGELOG +# Changelog -## 2.1.0 +![keep a changelog](https://img.shields.io/badge/Keep%20a%20Changelog-v1.1.0-brightgreen.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmMTVkMzAiIHZpZXdCb3g9IjAgMCAxODcgMTg1Ij48cGF0aCBkPSJNNjIgN2MtMTUgMy0yOCAxMC0zNyAyMmExMjIgMTIyIDAgMDAtMTggOTEgNzQgNzQgMCAwMDE2IDM4YzYgOSAxNCAxNSAyNCAxOGE4OSA4OSAwIDAwMjQgNCA0NSA0NSAwIDAwNiAwbDMtMSAxMy0xYTE1OCAxNTggMCAwMDU1LTE3IDYzIDYzIDAgMDAzNS01MiAzNCAzNCAwIDAwLTEtNWMtMy0xOC05LTMzLTE5LTQ3LTEyLTE3LTI0LTI4LTM4LTM3QTg1IDg1IDAgMDA2MiA3em0zMCA4YzIwIDQgMzggMTQgNTMgMzEgMTcgMTggMjYgMzcgMjkgNTh2MTJjLTMgMTctMTMgMzAtMjggMzhhMTU1IDE1NSAwIDAxLTUzIDE2bC0xMyAyaC0xYTUxIDUxIDAgMDEtMTItMWwtMTctMmMtMTMtNC0yMy0xMi0yOS0yNy01LTEyLTgtMjQtOC0zOWExMzMgMTMzIDAgMDE4LTUwYzUtMTMgMTEtMjYgMjYtMzMgMTQtNyAyOS05IDQ1LTV6TTQwIDQ1YTk0IDk0IDAgMDAtMTcgNTQgNzUgNzUgMCAwMDYgMzJjOCAxOSAyMiAzMSA0MiAzMiAyMSAyIDQxLTIgNjAtMTRhNjAgNjAgMCAwMDIxLTE5IDUzIDUzIDAgMDA5LTI5YzAtMTYtOC0zMy0yMy01MWE0NyA0NyAwIDAwLTUtNWMtMjMtMjAtNDUtMjYtNjctMTgtMTIgNC0yMCA5LTI2IDE4em0xMDggNzZhNTAgNTAgMCAwMS0yMSAyMmMtMTcgOS0zMiAxMy00OCAxMy0xMSAwLTIxLTMtMzAtOS01LTMtOS05LTEzLTE2YTgxIDgxIDAgMDEtNi0zMiA5NCA5NCAwIDAxOC0zNSA5MCA5MCAwIDAxNi0xMmwxLTJjNS05IDEzLTEzIDIzLTE2IDE2LTUgMzItMyA1MCA5IDEzIDggMjMgMjAgMzAgMzYgNyAxNSA3IDI5IDAgNDJ6bS00My03M2MtMTctOC0zMy02LTQ2IDUtMTAgOC0xNiAyMC0xOSAzN2E1NCA1NCAwIDAwNSAzNGM3IDE1IDIwIDIzIDM3IDIyIDIyLTEgMzgtOSA0OC0yNGE0MSA0MSAwIDAwOC0yNCA0MyA0MyAwIDAwLTEtMTJjLTYtMTgtMTYtMzEtMzItMzh6bS0yMyA5MWgtMWMtNyAwLTE0LTItMjEtN2EyNyAyNyAwIDAxLTEwLTEzIDU3IDU3IDAgMDEtNC0yMCA2MyA2MyAwIDAxNi0yNWM1LTEyIDEyLTE5IDI0LTIxIDktMyAxOC0yIDI3IDIgMTQgNiAyMyAxOCAyNyAzM3MtMiAzMS0xNiA0MGMtMTEgOC0yMSAxMS0zMiAxMXptMS0zNHYxNGgtOFY2OGg4djI4bDEwLTEwaDExbC0xNCAxNSAxNyAxOEg5NnoiLz48L3N2Zz4K) -* Merged https://github.com/aakb/itstyr/pull/14 - Upgraded symfony to 4.4.2. -* Merged https://github.com/aakb/itstyr/pull/13 - Added import run entity to track import run success. Changed report fields that are imported after change in Anmeldelsesportalen. +All notable changes to this project will be documented in this file. + +See [keep a changelog] for information about writing changes to this log. + +## [Unreleased] + +## [3.0.0] - 2025-06-13 + +* [PR-33](https://github.com/itk-dev/sysstatus/pull/33) + * Inlined actions + * Cleaned up report views +* [PR-32](https://github.com/itk-dev/sysstatus/pull/32) + 3644: Cleaned up template and controller +* [PR-31](https://github.com/itk-dev/sysstatus/pull/31) + Upgraded to Symfony 7.2 +* [PR-30](https://github.com/itk-dev/sysstatus/pull/30) + Upgraded and cleaned up +* Login and dashboard styling cleanup +* Added github actions. +* Added PHPStan. +* Updated composer setup. +* Update Symfony major version. +* Update EasyAdmin major version. +* Updated all packages to the newest version +* User migration away form FOS user bundle to custom entity types. +* Added user create/update CLI commands + +## [2.1.0] - 2020-01-22 + +* Merged [https://github.com/aakb/itstyr/pull/14](https://github.com/aakb/itstyr/pull/14) + Upgraded symfony to 4.4.2. +* Merged [https://github.com/aakb/itstyr/pull/13](https://github.com/aakb/itstyr/pull/13) + Added import run entity to track import run success. Changed report fields that are imported after change in + Anmeldelsesportalen. ## 2.0.0 @@ -100,8 +132,7 @@ * Added responsible user to systems and reports. * Changed NULL values to display as empty instead of black square. * Added reports/systems dashboards. -* Added script (itstyr:group:assign) to extract group from sysOwner for reports - and systems. +* Added script (itstyr:group:assign) to extract group from sysOwner for reports and systems. ## 1.1.0 @@ -123,3 +154,9 @@ * Adding notes to each system and report. * Adding general notes. * Basic user management. + +[keep a changelog]: https://keepachangelog.com/en/1.1.0/ + +[Unreleased]: https://github.com/itk-dev/sysstatus/compare/main...develop +[3.0.0]: https://github.com/itk-dev/sysstatus/releases/tag/3.0.0 +[2.1.0]: https://github.com/itk-dev/sysstatus/releases/tag/2.1.0 diff --git a/README.md b/README.md index 6822bca7..12108a88 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,34 @@ -# itstyr -Styringsværktøj til IT projekter +# ITStyr + +Styringsværktøj til IT projekter. + +## Upgrade 2.x -> 3.x + +To upgrade the database you have to do some manual steps to make the new doctrine 3.x migration work. + +First create the new migration table. + +```shell +docker compose exec phpfpm bin/console doctrine:migrations:sync-metadata-storage +``` + +Move old migrations and remove old table. Then run the migrations. + +```shell +docker compose exec phpfpm bin/console doctrine:query:sql 'INSERT INTO doctrine_migration_versions (version, executed_at, execution_time) SELECT concat("DoctrineMigrations\\Version", version), NULL, 1 FROM migration_versions;' +docker compose exec phpfpm bin/console doctrine:query:sql 'DROP TABLE migration_versions;' +docker compose exec phpfpm bin/console doctrine:migration:migrate +``` ## Setup locally ### Preset + Make sure you have a set of JSON files for testing import Commands. ### Start Docker containers -```sh +```shell docker compose up -d docker compose exec phpfpm composer install docker compose exec phpfpm bin/console doctrine:migrations:migrate --no-interaction @@ -24,22 +44,23 @@ docker compose exec phpfpm bin/console SuperUser You should now be able to browse to the application -``` - +```shell open "http://$(docker-compose port nginx 8080)" - ``` ## Import systems and reports -```sh -docker compose exec phpfpm bin/console itstyr:import:system PATH -docker compose exec phpfpm bin/console itstyr:import:report PATH + +```shell +docker compose exec phpfpm bin/console itstyr:import:system +docker compose exec phpfpm bin/console itstyr:import:report ``` ### Flowchart A helpful flowchart over the Entities, and Joinedtables. + Ilustrative figures meaning: + 1. Database = Database 2. Black square = Entities 3. Grey square = relations @@ -47,6 +68,7 @@ Ilustrative figures meaning: 5. arrow = relation between DB and Entity 6. bulletin = shows the mapping Entities in Jointables, and JoinCollums + ```mermaid flowchart TD Answers[Answers] @@ -92,4 +114,4 @@ flowchart TD Question --- |ManyToOne| Category ``` - + diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 00000000..73241e70 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,144 @@ +version: '3' + +# https://taskfile.dev/usage/#env-files +dotenv: ['.env.local', '.env'] + +vars: + # https://taskfile.dev/reference/templating/ + BASE_URL: '{{.TASK_BASE_URL | default .COMPOSE_SERVER_DOMAIN | default .COMPOSE_DOMAIN | default "https://hoeringsportal.local.itkdev.dk"}}' + DOCKER_COMPOSE: '{{.TASK_DOCKER_COMPOSE | default "docker compose"}}' + +tasks: + start: + cmds: + - task compose -- pull + - task compose -- up --detach --remove-orphans --wait + - task composer -- install + - task console -- doctrine:migrations:migrate --no-interaction + silent: true + + compose: + cmds: + - '{{.DOCKER_COMPOSE}} {{.CLI_ARGS}}' + + composer: + cmds: + - task compose -- exec phpfpm composer {{.CLI_ARGS}} + silent: true + + console: + cmds: + - task compose -- exec phpfpm bin/console {{.CLI_ARGS}} + silent: true + + coding-standards:apply: + desc: "Apply coding standards" + cmds: + - task: coding-standards:assets:apply + - task: coding-standards:composer:apply + - task: coding-standards:markdown:apply + - task: coding-standards:php:apply + - task: coding-standards:twig:apply + - task: coding-standards:yaml:apply + silent: true + + coding-standards:check: + desc: "Apply coding standards" + cmds: + - task: coding-standards:assets:check + - task: coding-standards:composer:check + - task: coding-standards:markdown:check + - task: coding-standards:php:check + - task: coding-standards:twig:check + - task: coding-standards:yaml:check + silent: true + + coding-standards:assets:apply: + desc: "Apply coding standards for assets" + cmds: + - task compose -- run --rm prettier 'assets/' --write + + coding-standards:assets:check: + desc: "Apply and check coding standards for assets" + cmds: + - task: coding-standards:assets:apply + - task compose -- run --rm prettier 'assets/' --check + + coding-standards:composer:apply: + desc: "Apply coding standards for Composer" + cmds: + - task composer -- normalize + + coding-standards:composer:check: + desc: "Apply and check coding standards for Composer" + cmds: + - task: coding-standards:composer:apply + - task composer -- audit + - task composer -- normalize --dry-run + - task composer -- validate --strict + + coding-standards:markdown:apply: + desc: "Apply coding standards for Markdown" + cmds: + - task compose -- run --rm markdownlint '**/*.md' --fix + + coding-standards:markdown:check: + desc: "Apply and check coding standards for Markdown" + cmds: + - task: coding-standards:markdown:apply + - task compose -- run --rm markdownlint '**/*.md' + + coding-standards:php:apply: + desc: "Apply coding standards for PHP" + cmds: + - task compose -- exec phpfpm vendor/bin/rector + - task compose -- exec phpfpm vendor/bin/php-cs-fixer fix + silent: true + + coding-standards:php:check: + desc: "Apply and check coding standards for PHP" + cmds: + - task: coding-standards:php:apply + - task compose -- exec phpfpm vendor/bin/rector --dry-run + - task compose -- exec phpfpm vendor/bin/php-cs-fixer check + silent: true + + coding-standards:twig:apply: + desc: "Apply coding standards for Twig" + cmds: + - task compose -- exec phpfpm vendor/bin/twig-cs-fixer fix + silent: true + + coding-standards:twig:check: + desc: "Apply and check coding standards for Twig" + cmds: + - task: coding-standards:twig:apply + - task compose -- exec phpfpm vendor/bin/twig-cs-fixer check + silent: true + + coding-standards:yaml:apply: + desc: "Apply coding standards for YAML" + cmds: + - task compose -- run --rm prettier --parser yaml phpstan*.neon 'config/**/*.{yml,yaml}' --write + + coding-standards:yaml:check: + desc: "Apply and check coding standards for YAML" + cmds: + - task: coding-standards:yaml:apply + - task compose -- run --rm prettier --parser yaml phpstan*.neon 'config/**/*.{yml,yaml}' --check + + code-analysis: + cmds: + - task compose -- exec phpfpm vendor/bin/phpstan + + docker-pull: + desc: "Pull all development docker images" + cmds: + - docker pull jauderho/prettier + - docker pull peterdavehello/markdownlint + - task compose -- pull + + default: + cmds: + - task --list-all + silent: true diff --git a/assets/app.js b/assets/app.js new file mode 100644 index 00000000..683fbe7a --- /dev/null +++ b/assets/app.js @@ -0,0 +1,7 @@ +/* + * Welcome to your app's main JavaScript file! + * + * This file will be included onto the page via the importmap() Twig function, + * which should already be in your base.html.twig. + */ +import "./styles/app.css"; diff --git a/public/arrow-down.svg b/assets/images/arrow-down.svg similarity index 100% rename from public/arrow-down.svg rename to assets/images/arrow-down.svg diff --git a/public/styles.css b/assets/styles/app.css similarity index 55% rename from public/styles.css rename to assets/styles/app.css index 5f31dad8..335396f1 100644 --- a/public/styles.css +++ b/assets/styles/app.css @@ -1,5 +1,6 @@ :root { --body-max-width: 100%; + --font-size-xs: 0.7rem; } .wrapper { @@ -48,14 +49,14 @@ } .custom-filters { - margin-bottom: .5em; + margin-bottom: 0.5em; } .custom-filters select.form-control { -webkit-appearance: none; -moz-appearance: none; -webkit-border-radius: 0; - background-image: url("arrow-down.svg"); + background-image: url("../images/arrow-down.svg"); background-position: 95% 50%; background-repeat: no-repeat; background-size: 16px; @@ -78,40 +79,13 @@ border: 0px; } -th.rotate { - height: 200px; - white-space: nowrap; - max-width: 55px; - padding: 0; -} - -th.rotate > div { - transform-origin: top left; - transform: translate(0px, 55px) rotate(315deg); - width: 300px; - max-height: 55px; - border-top: 1px solid #dee2e6; - padding: 5px 0 0 40px; - height: 55px; -} - -th.rotate > div > span { - padding: 5px 10px 5px 0px;; - display: block; - width: 265px; - overflow: hidden; - text-overflow: ellipsis; -} - -th.rotate > div > span a { - width: 800px; -} - -.table td, .table th { +.table td, +.table th { vertical-align: middle; } -.table td h3, .table th h3 { +.table td h3, +.table th h3 { margin-bottom: 0; } @@ -134,7 +108,7 @@ body.list table tbody td.dashboard--table-answer { } .dashboard--table-spacing { - background-color: #EEE; + background-color: #eee; height: 30px; } @@ -161,23 +135,23 @@ body.list table tbody td.dashboard--table-answer { } .smiley-icon + .in { - opacity: 1!important; + opacity: 1 !important; } -.smiley-icon-green svg path { +.smiley-icon-green svg path { fill: #008855; } -.smiley-icon-yellow svg path { - fill: #F6BD1D; +.smiley-icon-yellow svg path { + fill: #f6bd1d; } -.smiley-icon-red svg path { - fill: #D32F2F; +.smiley-icon-red svg path { + fill: #d32f2f; } -.smiley-icon-blue svg path { - fill: #3661D8; +.smiley-icon-blue svg path { + fill: #3661d8; } .smiley-icon-grey svg path { @@ -204,8 +178,8 @@ body.list table tbody td.dashboard--table-answer { /* Fix position of table heads while scrolling */ .affix { - top: 0; - z-index: 1040; + top: 0; + z-index: 1040; } .table-right-column { @@ -222,9 +196,11 @@ body.list table tbody td.dashboard--table-answer { justify-content: center; } -.current, .page, .next, .last { +.current, +.page, +.next, +.last { margin: 5px; - } .dashboard--table-cell { display: flex; @@ -240,7 +216,107 @@ body.list table tbody td.dashboard--table-answer { width: 300px; } +/* .ea-detail .field-group .field-label { width: 200px !important; +} + +.dashboard--table { + table { + th { + vertical-align: top; + font-size: var(--font-size-xs); + font-weight: normal; + line-height: 1.1; + } + } +} +*/ + +/* Don't let fragment links stand out */ +h2 { + a { + color: inherit; + } +} + +.ea-detail { + .field-group { + /* Show field values like input controls for improved (?) readability */ + .field-label { + margin-top: 5px; + } + + .field-value { + border: var(--border-width) var(--border-style) var(--border-color); + padding: 4px 7px 5px; + border-radius: var(--border-radius); + } + } + + /* Un-flex label and value for boolean fields back to label: value */ + .field-group.field-boolean { + flex-direction: initial; + + .field-label { + flex: initial; + margin: 0 15px 0 0; + min-inline-size: initial; + text-align: right; + } + + .field-value { + flex: initial; + inline-size: initial; + min-inline-size: initial; + text-align: initial; + } + } +} -} \ No newline at end of file +th.rotate { + height: 200px; + white-space: nowrap; + max-width: 55px; + padding: 0; + vertical-align: bottom; + + > div { + transform-origin: top left; + transform: translate(0px, 55px) rotate(315deg); + width: 300px; + max-height: 55px; + border-top: 1px solid #dee2e6; + padding: 5px 0 0 40px; + height: 55px; + + > span { + padding: 5px 10px 5px 0px; + display: block; + width: 265px; + overflow: hidden; + text-overflow: ellipsis; + + a { + width: 800px; + } + } + } +} + +/* Help our theme.themeCategories and category.questions table stuff fall into place visually (cf. template/admin/form.html.twig) */ +.field-collection .table-ea-collection { + td { + vertical-align: top; + } + + tr.field-collection-item { + display: table-row; + + .field-collection-delete-button { + inset-block-start: initial; + inset-inline-end: initial; + position: initial; + } + } +} diff --git a/composer.json b/composer.json index 39dab7f5..2eddabd0 100644 --- a/composer.json +++ b/composer.json @@ -4,36 +4,47 @@ "license": "proprietary", "type": "project", "require": { - "php": ">=8.1", + "php": ">=8.3", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/annotations": "^2.0", - "doctrine/dbal": "^3.6", - "doctrine/doctrine-bundle": "^2.8", - "doctrine/doctrine-migrations-bundle": "^3.2", - "doctrine/orm": "^2.14", - "easycorp/easyadmin-bundle": "^4.6", - "fresh/doctrine-enum-bundle": "^9.0", - "gedmo/doctrine-extensions": "^3.16", - "knplabs/knp-paginator-bundle": "^6.1", - "phpoffice/phpspreadsheet": "^1.28", - "stof/doctrine-extensions-bundle": "^1.7", - "symfony/console": "6.4.*", - "symfony/dotenv": "6.4.*", - "symfony/flex": "^2", - "symfony/framework-bundle": "6.4.*", - "symfony/runtime": "6.4.*", - "symfony/security-bundle": "6.4.*", - "symfony/validator": "6.4.*", - "symfony/yaml": "6.4.*" + "doctrine/dbal": "^3.9.4", + "doctrine/doctrine-bundle": "^2.14", + "doctrine/doctrine-migrations-bundle": "^3.4.1", + "doctrine/orm": "^2.20.2", + "easycorp/easyadmin-bundle": "^4.24", + "fresh/doctrine-enum-bundle": "^10.1", + "gedmo/doctrine-extensions": "^3.19", + "knplabs/knp-paginator-bundle": "^6.7", + "phpoffice/phpspreadsheet": "^1.29.10", + "stof/doctrine-extensions-bundle": "^1.13", + "symfony/asset": "~7.2.0", + "symfony/asset-mapper": "~7.2.3", + "symfony/console": "~7.2.1", + "symfony/dotenv": "~7.2.0", + "symfony/flex": "^2.5", + "symfony/framework-bundle": "~7.2.4", + "symfony/runtime": "~7.2.3", + "symfony/security-bundle": "~7.2.3", + "symfony/twig-bundle": "~7.2.0", + "symfony/validator": "~7.2.4", + "symfony/yaml": "~7.2.3", + "twig/extra-bundle": "^2.12 || ^3.20", + "twig/string-extra": "^3.20", + "twig/twig": "^2.12 || ^3.20" }, "require-dev": { - "ergebnis/composer-normalize": "^2.43", - "friendsofphp/php-cs-fixer": "^3.66", - "symfony/maker-bundle": "^1.48", - "symfony/phpunit-bridge": "*", - "symfony/stopwatch": "6.4.*", - "symfony/web-profiler-bundle": "6.4.*" + "ergebnis/composer-normalize": "^2.45", + "friendsofphp/php-cs-fixer": "^3.73.1", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.11", + "phpstan/phpstan-doctrine": "^2.0.2", + "rector/rector": "^2.0.10", + "symfony/debug-bundle": "~7.2.0", + "symfony/maker-bundle": "^1.62.1", + "symfony/phpunit-bridge": ">=7.2", + "symfony/stopwatch": "~7.2.4", + "symfony/web-profiler-bundle": "~7.2.4", + "vincentlanglet/twig-cs-fixer": "^3.5.1" }, "replace": { "symfony/polyfill-ctype": "*", @@ -63,6 +74,7 @@ "allow-plugins": { "ergebnis/composer-normalize": true, "php-http/discovery": true, + "phpstan/extension-installer": true, "symfony/flex": true, "symfony/runtime": true }, @@ -70,8 +82,8 @@ }, "extra": { "symfony": { - "allow-contrib": false, - "require": "6.4.*" + "allow-contrib": true, + "require": "7.2.*" } }, "scripts": { @@ -83,7 +95,20 @@ ], "auto-scripts": { "cache:clear": "symfony-cmd", - "assets:install %PUBLIC_DIR%": "symfony-cmd" - } + "assets:install %PUBLIC_DIR%": "symfony-cmd", + "importmap:install": "symfony-cmd" + }, + "coding-standards-analysis": [ + "./vendor/bin/phpstan analyse src migrations" + ], + "coding-standards-apply": [ + "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix" + ], + "coding-standards-baseline": [ + "./vendor/bin/phpstan analyse src migrations --generate-baseline" + ], + "coding-standards-check": [ + "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --dry-run" + ] } } diff --git a/composer.lock b/composer.lock index e6784d66..9b3f6210 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "35f1f5af197f3ad45f17f8b1144ed14b", + "content-hash": "411b1ccd04eb8380ea851afbfb884e54", "packages": [ { "name": "behat/transliterator", @@ -53,43 +53,48 @@ "issues": "https://github.com/Behat/Transliterator/issues", "source": "https://github.com/Behat/Transliterator/tree/v1.5.0" }, + "abandoned": true, "time": "2022-03-30T09:27:43+00:00" }, { - "name": "doctrine/annotations", - "version": "2.0.1", + "name": "composer/pcre", + "version": "3.3.2", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" + "php": "^7.4 || ^8.0" }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" + "conflict": { + "phpstan/phpstan": "<1.11.10" }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" }, "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -98,38 +103,118 @@ ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" }, { - "name": "Roman Borschel", - "email": "roman@code-factory.org" + "url": "https://github.com/composer", + "type": "github" }, { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" }, { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" }, { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" } ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "description": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ - "annotations", - "docblock", - "parser" + "semantic", + "semver", + "validation", + "versioning" ], "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" }, - "time": "2023-02-02T22:02:53+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": "2024-09-19T14:15:21+00:00" }, { "name": "doctrine/cache", @@ -226,29 +311,29 @@ }, { "name": "doctrine/collections", - "version": "2.2.2", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "d8af7f248c74f195f7347424600fd9e17b57af59" + "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/d8af7f248c74f195f7347424600fd9e17b57af59", - "reference": "d8af7f248c74f195f7347424600fd9e17b57af59", + "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d", + "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d", "shasum": "" }, "require": { "doctrine/deprecations": "^1", - "php": "^8.1" + "php": "^8.1", + "symfony/polyfill-php84": "^1.30" }, "require-dev": { "doctrine/coding-standard": "^12", "ext-json": "*", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.11" + "phpunit/phpunit": "^10.5" }, "type": "library", "autoload": { @@ -292,7 +377,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.2.2" + "source": "https://github.com/doctrine/collections/tree/2.3.0" }, "funding": [ { @@ -308,24 +393,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T06:56:21+00:00" + "time": "2025-03-22T10:17:19+00:00" }, { "name": "doctrine/common", - "version": "3.4.4", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a" + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a", - "reference": "0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a", + "url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5", + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5", "shasum": "" }, "require": { - "doctrine/persistence": "^2.0 || ^3.0", + "doctrine/persistence": "^2.0 || ^3.0 || ^4.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -383,7 +468,7 @@ ], "support": { "issues": "https://github.com/doctrine/common/issues", - "source": "https://github.com/doctrine/common/tree/3.4.4" + "source": "https://github.com/doctrine/common/tree/3.5.0" }, "funding": [ { @@ -399,20 +484,20 @@ "type": "tidelift" } ], - "time": "2024-04-16T13:35:33+00:00" + "time": "2025-01-01T22:12:03+00:00" }, { "name": "doctrine/dbal", - "version": "3.9.0", + "version": "3.9.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "d8f68ea6cc00912e5313237130b8c8decf4d28c6" + "reference": "ec16c82f20be1a7224e65ac67144a29199f87959" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/d8f68ea6cc00912e5313237130b8c8decf4d28c6", - "reference": "d8f68ea6cc00912e5313237130b8c8decf4d28c6", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/ec16c82f20be1a7224e65ac67144a29199f87959", + "reference": "ec16c82f20be1a7224e65ac67144a29199f87959", "shasum": "" }, "require": { @@ -428,15 +513,13 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.11.7", - "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.20", - "psalm/plugin-phpunit": "0.18.4", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "9.6.22", "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "vimeo/psalm": "4.30.0" + "symfony/console": "^4.4|^5.4|^6.0|^7.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -496,7 +579,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.0" + "source": "https://github.com/doctrine/dbal/tree/3.9.4" }, "funding": [ { @@ -512,33 +595,34 @@ "type": "tidelift" } ], - "time": "2024-08-15T07:34:42+00:00" + "time": "2025-01-16T08:28:55+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, "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" + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -546,7 +630,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -557,68 +641,70 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2025-04-07T20:06:18+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "2.12.0", + "version": "2.14.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "5418e811a14724068e95e0ba43353b903ada530f" + "reference": "ca6a7350b421baf7fbdefbf9f4993292ed18effb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/5418e811a14724068e95e0ba43353b903ada530f", - "reference": "5418e811a14724068e95e0ba43353b903ada530f", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/ca6a7350b421baf7fbdefbf9f4993292ed18effb", + "reference": "ca6a7350b421baf7fbdefbf9f4993292ed18effb", "shasum": "" }, "require": { - "doctrine/cache": "^1.11 || ^2.0", "doctrine/dbal": "^3.7.0 || ^4.0", - "doctrine/persistence": "^2.2 || ^3", + "doctrine/persistence": "^3.1 || ^4", "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", + "php": "^8.1", + "symfony/cache": "^6.4 || ^7.0", + "symfony/config": "^6.4 || ^7.0", + "symfony/console": "^6.4 || ^7.0", + "symfony/dependency-injection": "^6.4 || ^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" + "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3", + "symfony/framework-bundle": "^6.4 || ^7.0", + "symfony/service-contracts": "^2.5 || ^3" }, "conflict": { "doctrine/annotations": ">=3.0", + "doctrine/cache": "< 1.11", "doctrine/orm": "<2.17 || >=4.0", - "twig/twig": "<1.34 || >=2.0 <2.4" + "symfony/var-exporter": "< 6.4.1 || 7.0.0", + "twig/twig": "<2.13 || >=3.0 <3.0.4" }, "require-dev": { "doctrine/annotations": "^1 || ^2", + "doctrine/cache": "^1.11 || ^2.0", "doctrine/coding-standard": "^12", "doctrine/deprecations": "^1.0", "doctrine/orm": "^2.17 || ^3.0", "friendsofphp/proxy-manager-lts": "^1.0", - "phpunit/phpunit": "^9.5.26", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^5", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9.6.22", "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/stopwatch": "^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": "^5.15" + "symfony/doctrine-messenger": "^6.4 || ^7.0", + "symfony/messenger": "^6.4 || ^7.0", + "symfony/phpunit-bridge": "^7.2", + "symfony/property-info": "^6.4 || ^7.0", + "symfony/security-bundle": "^6.4 || ^7.0", + "symfony/stopwatch": "^6.4 || ^7.0", + "symfony/string": "^6.4 || ^7.0", + "symfony/twig-bridge": "^6.4 || ^7.0", + "symfony/validator": "^6.4 || ^7.0", + "symfony/var-exporter": "^6.4.1 || ^7.0.1", + "symfony/web-profiler-bundle": "^6.4 || ^7.0", + "symfony/yaml": "^6.4 || ^7.0", + "twig/twig": "^2.13 || ^3.0.4" }, "suggest": { "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", @@ -663,7 +749,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.12.0" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.14.0" }, "funding": [ { @@ -679,26 +765,26 @@ "type": "tidelift" } ], - "time": "2024-03-19T07:20:37+00:00" + "time": "2025-03-22T17:28:21+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "3.3.1", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0" + "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", - "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/5a6ac7120c2924c4c070a869d08b11ccf9e277b9", + "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9", "shasum": "" }, "require": { "doctrine/doctrine-bundle": "^2.4", "doctrine/migrations": "^3.2", - "php": "^7.2|^8.0", + "php": "^7.2 || ^8.0", "symfony/deprecation-contracts": "^2.1 || ^3", "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" }, @@ -706,27 +792,20 @@ "composer/semver": "^3.0", "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", + "phpstan/phpstan": "^1.4 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpstan/phpstan-symfony": "^1.3 || ^2", + "phpunit/phpunit": "^8.5 || ^9.5", "symfony/phpunit-bridge": "^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6 || ^7", - "vimeo/psalm": "^4.30 || ^5.15" + "symfony/var-exporter": "^5.4 || ^6 || ^7" }, "type": "symfony-bundle", "autoload": { "psr-4": { - "Doctrine\\Bundle\\MigrationsBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Doctrine\\Bundle\\MigrationsBundle\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -755,7 +834,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.1" + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.4.2" }, "funding": [ { @@ -771,7 +850,7 @@ "type": "tidelift" } ], - "time": "2024-05-14T20:32:18+00:00" + "time": "2025-03-11T17:36:26+00:00" }, { "name": "doctrine/event-manager", @@ -1104,16 +1183,16 @@ }, { "name": "doctrine/migrations", - "version": "3.8.0", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c" + "reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/535a70dcbd88b8c6ba945be050977457f4f4c06c", - "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/325b61e41d032f5f7d7e2d11cbefff656eadc9ab", + "reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab", "shasum": "" }, "require": { @@ -1133,9 +1212,10 @@ "require-dev": { "doctrine/coding-standard": "^12", "doctrine/orm": "^2.13 || ^3", - "doctrine/persistence": "^2 || ^3", + "doctrine/persistence": "^2 || ^3 || ^4", "doctrine/sql-formatter": "^1.0", "ext-pdo_sqlite": "*", + "fig/log-test": "^1", "phpstan/phpstan": "^1.10", "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.3", @@ -1186,7 +1266,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.8.0" + "source": "https://github.com/doctrine/migrations/tree/3.9.0" }, "funding": [ { @@ -1202,20 +1282,20 @@ "type": "tidelift" } ], - "time": "2024-06-26T14:12:46+00:00" + "time": "2025-03-26T06:48:45+00:00" }, { "name": "doctrine/orm", - "version": "2.19.7", + "version": "2.20.3", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "168ac31084226f94d42e7461a40ff5607a56bd35" + "reference": "17d28b5c4cac212ca92730d9a26e32a0b1516126" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/168ac31084226f94d42e7461a40ff5607a56bd35", - "reference": "168ac31084226f94d42e7461a40ff5607a56bd35", + "url": "https://api.github.com/repos/doctrine/orm/zipball/17d28b5c4cac212ca92730d9a26e32a0b1516126", + "reference": "17d28b5c4cac212ca92730d9a26e32a0b1516126", "shasum": "" }, "require": { @@ -1242,16 +1322,17 @@ }, "require-dev": { "doctrine/annotations": "^1.13 || ^2", - "doctrine/coding-standard": "^9.0.2 || ^12.0", + "doctrine/coding-standard": "^9.0.2 || ^13.0", "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.11.1", + "phpstan/extension-installer": "~1.1.0 || ^1.4", + "phpstan/phpstan": "~1.4.10 || 2.0.3", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", - "squizlabs/php_codesniffer": "3.7.2", + "squizlabs/php_codesniffer": "3.12.0", "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.24.0" + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1301,22 +1382,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.19.7" + "source": "https://github.com/doctrine/orm/tree/2.20.3" }, - "time": "2024-08-23T06:54:57+00:00" + "time": "2025-05-02T17:07:53+00:00" }, { "name": "doctrine/persistence", - "version": "3.3.3", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "b337726451f5d530df338fc7f68dee8781b49779" + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/b337726451f5d530df338fc7f68dee8781b49779", - "reference": "b337726451f5d530df338fc7f68dee8781b49779", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/0ea965320cec355dba75031c1b23d4c78362e3ff", + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff", "shasum": "" }, "require": { @@ -1330,12 +1411,11 @@ "require-dev": { "doctrine/coding-standard": "^12", "doctrine/common": "^3.0", - "phpstan/phpstan": "1.11.1", + "phpstan/phpstan": "1.12.7", "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.24.0" + "phpunit/phpunit": "^8.5.38 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -1384,7 +1464,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.3.3" + "source": "https://github.com/doctrine/persistence/tree/3.4.0" }, "funding": [ { @@ -1400,20 +1480,20 @@ "type": "tidelift" } ], - "time": "2024-06-20T10:14:30+00:00" + "time": "2024-10-30T19:48:12+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.4.1", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891" + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/7f83911cc5eba870de7ebb11283972483f7e2891", - "reference": "7f83911cc5eba870de7ebb11283972483f7e2891", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8", + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8", "shasum": "" }, "require": { @@ -1421,9 +1501,9 @@ }, "require-dev": { "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "phpunit/phpunit": "^10.5" }, "bin": [ "bin/sql-formatter" @@ -1453,29 +1533,29 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.4.1" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2" }, - "time": "2024-08-05T20:32:22+00:00" + "time": "2025-01-24T11:45:48+00:00" }, { "name": "easycorp/easyadmin-bundle", - "version": "v4.11.1", + "version": "v4.24.7", "source": { "type": "git", "url": "https://github.com/EasyCorp/EasyAdminBundle.git", - "reference": "d0945053e9dbf81d0c10f8cacec25c8ec5e87053" + "reference": "b61cd46c454d853438ded3ca21eac1ad537589aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/d0945053e9dbf81d0c10f8cacec25c8ec5e87053", - "reference": "d0945053e9dbf81d0c10f8cacec25c8ec5e87053", + "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/b61cd46c454d853438ded3ca21eac1ad537589aa", + "reference": "b61cd46c454d853438ded3ca21eac1ad537589aa", "shasum": "" }, "require": { "doctrine/doctrine-bundle": "^2.5", - "doctrine/orm": "^2.10|^3.0", + "doctrine/orm": "^2.12|^3.0", "ext-json": "*", - "php": ">=8.0.2", + "php": ">=8.1", "symfony/asset": "^5.4|^6.0|^7.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/config": "^5.4|^6.0|^7.0", @@ -1493,24 +1573,31 @@ "symfony/security-bundle": "^5.4|^6.0|^7.0", "symfony/string": "^5.4|^6.0|^7.0", "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4.48|^6.4.16|^7.1.9", "symfony/twig-bundle": "^5.4|^6.0|^7.0", "symfony/uid": "^5.4|^6.0|^7.0", - "symfony/validator": "^5.4|^6.0|^7.0" + "symfony/ux-twig-component": "^2.21", + "symfony/validator": "^5.4|^6.0|^7.0", + "twig/extra-bundle": "^3.17", + "twig/html-extra": "^3.17", + "twig/twig": "^3.20" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "^3.4|3.5.x-dev", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-phpunit": "^1.2", - "phpstan/phpstan-strict-rules": "^1.4", - "phpstan/phpstan-symfony": "^1.2", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", "psr/log": "^1.0", "symfony/browser-kit": "^5.4|^6.0|^7.0", "symfony/css-selector": "^5.4|^6.0|^7.0", "symfony/debug-bundle": "^5.4|^6.0|^7.0", "symfony/dom-crawler": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/phpunit-bridge": "^5.4|^6.0|^7.0" + "symfony/phpunit-bridge": "^6.1|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0" }, "type": "symfony-bundle", "extra": { @@ -1542,7 +1629,7 @@ ], "support": { "issues": "https://github.com/EasyCorp/EasyAdminBundle/issues", - "source": "https://github.com/EasyCorp/EasyAdminBundle/tree/v4.11.1" + "source": "https://github.com/EasyCorp/EasyAdminBundle/tree/v4.24.7" }, "funding": [ { @@ -1550,24 +1637,24 @@ "type": "github" } ], - "time": "2024-08-06T18:21:54+00:00" + "time": "2025-05-14T17:55:05+00:00" }, { "name": "ezyang/htmlpurifier", - "version": "v4.17.0", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" + "reference": "cb56001e54359df7ae76dc522d08845dc741621b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -1609,37 +1696,37 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" }, - "time": "2023-11-17T15:01:25+00:00" + "time": "2024-11-01T03:51:45+00:00" }, { "name": "fresh/doctrine-enum-bundle", - "version": "v9.2.0", + "version": "v10.1.0", "source": { "type": "git", "url": "https://github.com/fre5h/DoctrineEnumBundle.git", - "reference": "60a0d7299b8825a6f2cef84da78a7426a38bc236" + "reference": "0a143fec8baa062a3acc714d2733edd00ed45129" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fre5h/DoctrineEnumBundle/zipball/60a0d7299b8825a6f2cef84da78a7426a38bc236", - "reference": "60a0d7299b8825a6f2cef84da78a7426a38bc236", + "url": "https://api.github.com/repos/fre5h/DoctrineEnumBundle/zipball/0a143fec8baa062a3acc714d2733edd00ed45129", + "reference": "0a143fec8baa062a3acc714d2733edd00ed45129", "shasum": "" }, "require": { "doctrine/common": "^3.4", - "doctrine/dbal": "^3.6", - "doctrine/doctrine-bundle": "^2.9", - "doctrine/orm": "^2.15", + "doctrine/dbal": "^3.7", + "doctrine/doctrine-bundle": "^2.11", + "doctrine/orm": "^2.16|^3.0", "php": ">=8.1", - "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.1", - "symfony/doctrine-bridge": "^6.1", - "symfony/framework-bundle": "^6.1", - "symfony/http-kernel": "^6.1", - "symfony/validator": "^6.1", - "twig/twig": "^3.6" + "symfony/config": "^7.0", + "symfony/dependency-injection": "^7.0", + "symfony/doctrine-bridge": "^7.0", + "symfony/framework-bundle": "^7.0", + "symfony/http-kernel": "^7.0", + "symfony/validator": "^7.0", + "twig/twig": "^3.8" }, "require-dev": { "escapestudios/symfony2-coding-standard": "^3.13", @@ -1648,8 +1735,8 @@ "phpstan/phpstan-doctrine": "^1.3", "phpstan/phpstan-phpunit": "^1.3", "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^10.1", - "slam/phpstan-extensions": "^6.0", + "phpunit/phpunit": "^10.5", + "slam/phpstan-extensions": "^6.1", "symfony/form": "^6.1" }, "type": "symfony-bundle", @@ -1695,7 +1782,7 @@ "support": { "email": "genvaldartem@gmail.com", "issues": "https://github.com/fre5h/DoctrineEnumBundle/issues", - "source": "https://github.com/fre5h/DoctrineEnumBundle/tree/v9.2.0" + "source": "https://github.com/fre5h/DoctrineEnumBundle/tree/v10.1.0" }, "funding": [ { @@ -1703,29 +1790,28 @@ "type": "github" } ], - "time": "2023-12-01T10:32:30+00:00" + "time": "2024-03-29T06:45:06+00:00" }, { "name": "gedmo/doctrine-extensions", - "version": "v3.16.1", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/doctrine-extensions/DoctrineExtensions.git", - "reference": "e85560ed96f977b8c29428a99222cb2ef2f0e80d" + "reference": "ea1d37586b8e4bae2a815feb38b177894b12c44c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/e85560ed96f977b8c29428a99222cb2ef2f0e80d", - "reference": "e85560ed96f977b8c29428a99222cb2ef2f0e80d", + "url": "https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/ea1d37586b8e4bae2a815feb38b177894b12c44c", + "reference": "ea1d37586b8e4bae2a815feb38b177894b12c44c", "shasum": "" }, "require": { "behat/transliterator": "^1.2", "doctrine/collections": "^1.2 || ^2.0", - "doctrine/common": "^2.13 || ^3.0", "doctrine/deprecations": "^1.0", "doctrine/event-manager": "^1.2 || ^2.0", - "doctrine/persistence": "^2.2 || ^3.0", + "doctrine/persistence": "^2.2 || ^3.0 || ^4.0", "php": "^7.4 || ^8.0", "psr/cache": "^1 || ^2 || ^3", "psr/clock": "^1", @@ -1733,24 +1819,26 @@ }, "conflict": { "doctrine/annotations": "<1.13 || >=3.0", - "doctrine/dbal": "<3.2 || >=4.0", + "doctrine/common": "<2.13 || >=4.0", + "doctrine/dbal": "<3.7 || >=5.0", "doctrine/mongodb-odm": "<2.3 || >=3.0", - "doctrine/orm": "<2.14.0 || 2.16.0 || 2.16.1 || >=4.0" + "doctrine/orm": "<2.20 || >=3.0 <3.3 || >=4.0" }, "require-dev": { "doctrine/annotations": "^1.13 || ^2.0", "doctrine/cache": "^1.11 || ^2.0", - "doctrine/dbal": "^3.2", + "doctrine/common": "^2.13 || ^3.0", + "doctrine/dbal": "^3.7 || ^4.0", "doctrine/doctrine-bundle": "^2.3", "doctrine/mongodb-odm": "^2.3", - "doctrine/orm": "^2.14.0 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.14.0", + "doctrine/orm": "^2.20 || ^3.3", + "friendsofphp/php-cs-fixer": "^3.70", "nesbot/carbon": "^2.71 || ^3.0", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-doctrine": "^1.4", - "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan": "^2.1.1", + "phpstan/phpstan-doctrine": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.3", "phpunit/phpunit": "^9.6", - "rector/rector": "^1.1", + "rector/rector": "^2.0.6", "symfony/console": "^5.4 || ^6.0 || ^7.0", "symfony/doctrine-bridge": "^5.4 || ^6.0 || ^7.0", "symfony/phpunit-bridge": "^6.0 || ^7.0", @@ -1810,10 +1898,9 @@ "uploadable" ], "support": { - "email": "gediminas.morkevicius@gmail.com", + "docs": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/main/doc", "issues": "https://github.com/doctrine-extensions/DoctrineExtensions/issues", - "source": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.16.1", - "wiki": "https://github.com/Atlantic18/DoctrineExtensions/tree/main/doc" + "source": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.20.0" }, "funding": [ { @@ -1833,24 +1920,24 @@ "type": "github" } ], - "time": "2024-06-25T16:22:14+00:00" + "time": "2025-04-04T17:19:27+00:00" }, { "name": "knplabs/knp-components", - "version": "v4.4.0", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/KnpLabs/knp-components.git", - "reference": "59ef316e34e814449d8718d7151946bdbb5e553f" + "reference": "eabf39263fff305c0024820c3736e5b03e7edf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/59ef316e34e814449d8718d7151946bdbb5e553f", - "reference": "59ef316e34e814449d8718d7151946bdbb5e553f", + "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/eabf39263fff305c0024820c3736e5b03e7edf50", + "reference": "eabf39263fff305c0024820c3736e5b03e7edf50", "shasum": "" }, "require": { - "php": "^8.0", + "php": "^8.1", "symfony/event-dispatcher-contracts": "^3.0" }, "conflict": { @@ -1863,7 +1950,7 @@ "doctrine/phpcr-odm": "^1.8 || ^2.0", "ext-pdo_sqlite": "*", "jackalope/jackalope-doctrine-dbal": "^1.12 || ^2.0", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^10.5 || ^11.3", "propel/propel1": "^1.7", "ruflin/elastica": "^7.0", "solarium/solarium": "^6.0", @@ -1885,7 +1972,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -1918,26 +2005,26 @@ ], "support": { "issues": "https://github.com/KnpLabs/knp-components/issues", - "source": "https://github.com/KnpLabs/knp-components/tree/v4.4.0" + "source": "https://github.com/KnpLabs/knp-components/tree/v5.2.0" }, - "time": "2024-04-23T07:05:01+00:00" + "time": "2025-03-20T07:35:37+00:00" }, { "name": "knplabs/knp-paginator-bundle", - "version": "v6.4.0", + "version": "v6.8.1", "source": { "type": "git", "url": "https://github.com/KnpLabs/KnpPaginatorBundle.git", - "reference": "a9cbcb3c6be5868a2e16a599c7438149c40b4bda" + "reference": "038c50cf7d5da5e55533f6e803aeae73eb8b8d45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpPaginatorBundle/zipball/a9cbcb3c6be5868a2e16a599c7438149c40b4bda", - "reference": "a9cbcb3c6be5868a2e16a599c7438149c40b4bda", + "url": "https://api.github.com/repos/KnpLabs/KnpPaginatorBundle/zipball/038c50cf7d5da5e55533f6e803aeae73eb8b8d45", + "reference": "038c50cf7d5da5e55533f6e803aeae73eb8b8d45", "shasum": "" }, "require": { - "knplabs/knp-components": "^4.1", + "knplabs/knp-components": "^4.4 || ^5.0", "php": "^8.1", "symfony/config": "^6.4 || ^7.0", "symfony/dependency-injection": "^6.4 || ^7.0", @@ -1949,15 +2036,15 @@ "twig/twig": "^3.0" }, "require-dev": { - "phpstan/phpstan": "^1.11", - "phpunit/phpunit": "^9.6", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^10.5 || ^11.5 || ^12.0", "symfony/expression-language": "^6.4 || ^7.0", "symfony/templating": "^6.4 || ^7.0" }, "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "6.x-dev" } }, "autoload": { @@ -1992,37 +2079,38 @@ ], "support": { "issues": "https://github.com/KnpLabs/KnpPaginatorBundle/issues", - "source": "https://github.com/KnpLabs/KnpPaginatorBundle/tree/v6.4.0" + "source": "https://github.com/KnpLabs/KnpPaginatorBundle/tree/v6.8.1" }, - "time": "2024-05-21T16:15:16+00:00" + "time": "2025-05-20T07:07:41+00:00" }, { "name": "maennchen/zipstream-php", - "version": "3.1.0", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1" + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-zlib": "*", - "php-64bit": "^8.1" + "php-64bit": "^8.2" }, "require-dev": { + "brianium/paratest": "^7.7", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.16", "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^10.0", - "vimeo/psalm": "^5.0" + "phpunit/phpunit": "^11.0", + "vimeo/psalm": "^6.0" }, "suggest": { "guzzlehttp/psr7": "^2.4", @@ -2063,19 +2151,15 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" }, "funding": [ { "url": "https://github.com/maennchen", "type": "github" - }, - { - "url": "https://opencollective.com/zipstream", - "type": "open_collective" } ], - "time": "2023-06-21T14:59:35+00:00" + "time": "2025-01-27T12:07:53+00:00" }, { "name": "markbaker/complex", @@ -2186,19 +2270,20 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.29.0", + "version": "1.29.10", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" + "reference": "c80041b1628c4f18030407134fe88303661d4e4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e", + "reference": "c80041b1628c4f18030407134fe88303661d4e4e", "shasum": "" }, "require": { + "composer/pcre": "^1||^2||^3", "ext-ctype": "*", "ext-dom": "*", "ext-fileinfo": "*", @@ -2223,14 +2308,14 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-main", - "dompdf/dompdf": "^1.0 || ^2.0", + "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", "friendsofphp/php-cs-fixer": "^3.2", "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", + "phpunit/phpunit": "^8.5 || ^9.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -2285,9 +2370,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10" }, - "time": "2023-06-14T22:48:31+00:00" + "time": "2025-02-08T02:56:14+00:00" }, { "name": "psr/cache", @@ -2651,16 +2736,16 @@ }, { "name": "psr/log", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "79dff0b268932c640297f5208d6298f71855c03e" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e", - "reference": "79dff0b268932c640297f5208d6298f71855c03e", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -2695,9 +2780,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.1" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2024-08-21T13:31:24+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "psr/simple-cache", @@ -2752,36 +2837,37 @@ }, { "name": "stof/doctrine-extensions-bundle", - "version": "v1.12.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/stof/StofDoctrineExtensionsBundle.git", - "reference": "473ae65598fa4160654c350e139e20ee75d9a91a" + "reference": "bdf3eb10baeb497ac5985b8f78a6cf55862c2662" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/473ae65598fa4160654c350e139e20ee75d9a91a", - "reference": "473ae65598fa4160654c350e139e20ee75d9a91a", + "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/bdf3eb10baeb497ac5985b8f78a6cf55862c2662", + "reference": "bdf3eb10baeb497ac5985b8f78a6cf55862c2662", "shasum": "" }, "require": { - "gedmo/doctrine-extensions": "^3.15.0", - "php": "^7.4 || ^8.0", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0" + "gedmo/doctrine-extensions": "^3.20.0", + "php": "^8.1", + "symfony/cache": "^6.4 || ^7.0", + "symfony/config": "^6.4 || ^7.0", + "symfony/dependency-injection": "^6.4 || ^7.0", + "symfony/event-dispatcher": "^6.4 || ^7.0", + "symfony/http-kernel": "^6.4 || ^7.0", + "symfony/translation-contracts": "^2.5 || ^3.5" }, "require-dev": { - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.5", - "phpstan/phpstan-symfony": "^1.3", - "symfony/mime": "^5.4 || ^6.0 || ^7.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", + "symfony/mime": "^6.4 || ^7.0", "symfony/phpunit-bridge": "^v6.4.1 || ^7.0.1", - "symfony/security-core": "^5.4 || ^6.0 || ^7.0" + "symfony/security-core": "^6.4 || ^7.0" }, "suggest": { "doctrine/doctrine-bundle": "to use the ORM extensions", @@ -2826,34 +2912,34 @@ ], "support": { "issues": "https://github.com/stof/StofDoctrineExtensionsBundle/issues", - "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.12.0" + "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.14.0" }, - "time": "2024-06-10T12:27:27+00:00" + "time": "2025-05-01T08:00:32+00:00" }, { "name": "symfony/asset", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "c668aa320e26b7379540368832b9d1dd43d32603" + "reference": "cb926cd59fefa1f9b4900b3695f0f846797ba5c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/c668aa320e26b7379540368832b9d1dd43d32603", - "reference": "c668aa320e26b7379540368832b9d1dd43d32603", + "url": "https://api.github.com/repos/symfony/asset/zipball/cb926cd59fefa1f9b4900b3695f0f846797ba5c0", + "reference": "cb926cd59fefa1f9b4900b3695f0f846797ba5c0", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "conflict": { - "symfony/http-foundation": "<5.4" + "symfony/http-foundation": "<6.4" }, "require-dev": { - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0" + "symfony/http-client": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2881,7 +2967,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v6.4.8" + "source": "https://github.com/symfony/asset/tree/v7.2.0" }, "funding": [ { @@ -2897,61 +2983,48 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { - "name": "symfony/cache", - "version": "v6.4.10", + "name": "symfony/asset-mapper", + "version": "v7.2.5", "source": { "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc" + "url": "https://github.com/symfony/asset-mapper.git", + "reference": "6428e4b6d8cff9c5fe6f40ddbee4c9f6bfdaa0b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/6702d2d777260e6ff3451fee2d7d78ab5f715cdc", - "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc", + "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/6428e4b6d8cff9c5fe6f40ddbee4c9f6bfdaa0b8", + "reference": "6428e4b6d8cff9c5fe6f40ddbee4c9f6bfdaa0b8", "shasum": "" }, "require": { - "php": ">=8.1", - "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.3.6|^7.0" + "composer/semver": "^3.0", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^7.1", + "symfony/http-client": "^6.4|^7.0" }, "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/var-dumper": "<5.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" + "symfony/framework-bundle": "<6.4" }, "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1|^2.0", - "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/asset": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/event-dispatcher-contracts": "^3.0", + "symfony/finder": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Cache\\": "" + "Symfony\\Component\\AssetMapper\\": "" }, - "classmap": [ - "Traits/ValueWrapper.php" - ], "exclude-from-classmap": [ "/Tests/" ] @@ -2962,22 +3035,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": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "description": "Maps directories of assets & makes them available in a public directory with versioned filenames.", "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.10" + "source": "https://github.com/symfony/asset-mapper/tree/v7.2.5" }, "funding": [ { @@ -2993,37 +3062,135 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:05:49+00:00" + "time": "2025-03-26T11:29:07+00:00" }, { - "name": "symfony/cache-contracts", - "version": "v3.5.0", + "name": "symfony/cache", + "version": "v7.2.6", "source": { "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" + "url": "https://github.com/symfony/cache.git", + "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "url": "https://api.github.com/repos/symfony/cache/zipball/8b49dde3f5a5e9867595a3a269977f78418d75ee", + "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/cache": "^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" }, - "autoload": { + "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/clock": "^6.4|^7.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.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-08T09:06:23+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { "psr-4": { "Symfony\\Contracts\\Cache\\": "" } @@ -3053,7 +3220,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" }, "funding": [ { @@ -3069,24 +3236,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/clock", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "7a4840efd17135cbd547e41ec49fb910ed4f8b98" + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/7a4840efd17135cbd547e41ec49fb910ed4f8b98", - "reference": "7a4840efd17135cbd547e41ec49fb910ed4f8b98", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/clock": "^1.0", "symfony/polyfill-php83": "^1.28" }, @@ -3127,7 +3294,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v6.4.8" + "source": "https://github.com/symfony/clock/tree/v7.2.0" }, "funding": [ { @@ -3143,38 +3310,38 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:51:39+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/config", - "version": "v6.4.8", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35" + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/12e7e52515ce37191b193cf3365903c4f3951e35", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35", + "url": "https://api.github.com/repos/symfony/config/zipball/e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^7.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<5.4", + "symfony/finder": "<6.4", "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", + "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": "^5.4|^6.0|^7.0" + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3202,7 +3369,7 @@ "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/v6.4.8" + "source": "https://github.com/symfony/config/tree/v7.2.6" }, "funding": [ { @@ -3218,51 +3385,50 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-04-03T21:14:15+00:00" }, { "name": "symfony/console", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc" + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/504974cbe43d05f83b201d6498c206f16fc0cdbc", - "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc", + "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "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": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "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": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^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": { @@ -3296,7 +3462,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.10" + "source": "https://github.com/symfony/console/tree/v7.2.6" }, "funding": [ { @@ -3312,44 +3478,43 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "5caf9c5f6085f13b27d70a236b776c07e4a1c3eb" + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5caf9c5f6085f13b27d70a236b776c07e4a1c3eb", - "reference": "5caf9c5f6085f13b27d70a236b776c07e4a1c3eb", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2ca85496cde37f825bd14f7e3548e2793ca90712", + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/service-contracts": "^3.5", + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<6.1", - "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<6.3", - "symfony/yaml": "<5.4" + "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.1|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3377,7 +3542,7 @@ "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/v6.4.10" + "source": "https://github.com/symfony/dependency-injection/tree/v7.2.6" }, "funding": [ { @@ -3393,20 +3558,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T07:32:07+00:00" + "time": "2025-04-27T13:37:55+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -3414,12 +3579,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3444,7 +3609,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3460,71 +3625,72 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "0de9662441bce4670506d0c371cc819a9d0a7607" + "reference": "d030ea0d45746bf58d7905402bd45e9c35d412dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0de9662441bce4670506d0c371cc819a9d0a7607", - "reference": "0de9662441bce4670506d0c371cc819a9d0a7607", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/d030ea0d45746bf58d7905402bd45e9c35d412dd", + "reference": "d030ea0d45746bf58d7905402bd45e9c35d412dd", "shasum": "" }, "require": { - "doctrine/event-manager": "^1.2|^2", - "doctrine/persistence": "^3.1", - "php": ">=8.1", + "doctrine/event-manager": "^2", + "doctrine/persistence": "^3.1|^4", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "doctrine/dbal": "<2.13.1", + "doctrine/collections": "<1.8", + "doctrine/dbal": "<3.6", "doctrine/lexer": "<1.1", "doctrine/orm": "<2.15", - "symfony/cache": "<5.4", - "symfony/dependency-injection": "<6.2", - "symfony/form": "<5.4.38|>=6,<6.4.6|>=7,<7.0.6", - "symfony/http-foundation": "<6.3", - "symfony/http-kernel": "<6.2", - "symfony/lock": "<6.3", - "symfony/messenger": "<5.4", - "symfony/property-info": "<5.4", - "symfony/security-bundle": "<5.4", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/form": "<6.4.6|>=7,<7.0.6", + "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": "^2.13.1|^3|^4", + "doctrine/collections": "^1.8|^2.0", + "doctrine/data-fixtures": "^1.1|^2", + "doctrine/dbal": "^3.6|^4", "doctrine/orm": "^2.15|^3", "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^6.2|^7.0", - "symfony/doctrine-messenger": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/form": "^5.4.38|^6.4.6|^7.0.6", - "symfony/http-kernel": "^6.3|^7.0", - "symfony/lock": "^6.3|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/property-access": "^5.4|^6.0|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", - "symfony/proxy-manager-bridge": "^6.4", + "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.6|^7.0.6", + "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": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/type-info": "^7.1", + "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "type": "symfony-bridge", "autoload": { @@ -3552,7 +3718,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.10" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.2.6" }, "funding": [ { @@ -3568,32 +3734,32 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.10", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "2ae0c84cc9be0dc1eeb86016970b63c764d8472e" + "reference": "28347a897771d0c28e99b75166dd2689099f3045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/2ae0c84cc9be0dc1eeb86016970b63c764d8472e", - "reference": "2ae0c84cc9be0dc1eeb86016970b63c764d8472e", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/28347a897771d0c28e99b75166dd2689099f3045", + "reference": "28347a897771d0c28e99b75166dd2689099f3045", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "conflict": { - "symfony/console": "<5.4", - "symfony/process": "<5.4" + "symfony/console": "<6.4", + "symfony/process": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3626,7 +3792,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.10" + "source": "https://github.com/symfony/dotenv/tree/v7.2.0" }, "funding": [ { @@ -3642,26 +3808,26 @@ "type": "tidelift" } ], - "time": "2024-07-09T18:29:35+00:00" + "time": "2024-11-27T11:18:42+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.10", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0" + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/231f1b2ee80f72daa1972f7340297d67439224f0", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", @@ -3670,7 +3836,7 @@ "require-dev": { "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^5.4|^6.0|^7.0" + "symfony/serializer": "^6.4|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -3701,7 +3867,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.10" + "source": "https://github.com/symfony/error-handler/tree/v7.2.5" }, "funding": [ { @@ -3717,28 +3883,28 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-03-03T07:12:39+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -3747,13 +3913,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "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": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3781,7 +3947,7 @@ "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/v6.4.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -3797,20 +3963,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -3819,12 +3985,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3857,7 +4023,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -3873,29 +4039,29 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.9", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3923,7 +4089,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.9" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -3939,27 +4105,27 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:49:33+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v6.4.10", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "af29198d87112bebdd397bd7735fbd115997824c" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/af29198d87112bebdd397bd7735fbd115997824c", - "reference": "af29198d87112bebdd397bd7735fbd115997824c", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3987,7 +4153,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.10" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -4003,26 +4169,29 @@ "type": "tidelift" } ], - "time": "2024-07-24T07:06:38+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/flex", - "version": "v2.4.6", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "4dc11919791f81d087a12db2ab4c7e044431ef6b" + "reference": "ccc4d2dc15e90f0fed555d6078c3698396306cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/4dc11919791f81d087a12db2ab4c7e044431ef6b", - "reference": "4dc11919791f81d087a12db2ab4c7e044431ef6b", + "url": "https://api.github.com/repos/symfony/flex/zipball/ccc4d2dc15e90f0fed555d6078c3698396306cdd", + "reference": "ccc4d2dc15e90f0fed555d6078c3698396306cdd", "shasum": "" }, "require": { "composer-plugin-api": "^2.1", "php": ">=8.0" }, + "conflict": { + "composer/semver": "<1.7.2" + }, "require-dev": { "composer/composer": "^2.1", "symfony/dotenv": "^5.4|^6.0", @@ -4052,7 +4221,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.6" + "source": "https://github.com/symfony/flex/tree/v2.6.0" }, "funding": [ { @@ -4068,60 +4237,60 @@ "type": "tidelift" } ], - "time": "2024-04-27T10:22:22+00:00" + "time": "2025-05-21T07:23:28+00:00" }, { "name": "symfony/form", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "67dd6a3fd986cae9a90a8c2c526464c06f525863" + "reference": "e4e75b930d7a1ccd47bd3273c859c28e13d89b08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/67dd6a3fd986cae9a90a8c2c526464c06f525863", - "reference": "67dd6a3fd986cae9a90a8c2c526464c06f525863", + "url": "https://api.github.com/repos/symfony/form/zipball/e4e75b930d7a1ccd47bd3273c859c28e13d89b08", + "reference": "e4e75b930d7a1ccd47bd3273c859c28e13d89b08", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/options-resolver": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/options-resolver": "^6.4|^7.0", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-icu": "^1.21", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-access": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/doctrine-bridge": "<5.4.21|>=6,<6.2.7", - "symfony/error-handler": "<5.4", - "symfony/framework-bundle": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/error-handler": "<6.4", + "symfony/framework-bundle": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/translation": "<6.4.3|>=7.0,<7.0.3", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.3" + "symfony/twig-bridge": "<6.4" }, "require-dev": { "doctrine/collections": "^1.0|^2.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/expression-language": "^5.4|^6.0|^7.0", - "symfony/html-sanitizer": "^6.1|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", - "symfony/security-core": "^6.2|^7.0", - "symfony/security-csrf": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", - "symfony/uid": "^5.4|^6.0|^7.0", - "symfony/validator": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/translation": "^6.4.3|^7.0.3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4149,7 +4318,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v6.4.10" + "source": "https://github.com/symfony/form/tree/v7.2.6" }, "funding": [ { @@ -4165,111 +4334,113 @@ "type": "tidelift" } ], - "time": "2024-07-19T08:21:35+00:00" + "time": "2025-04-30T07:52:47+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.10", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b" + "reference": "c1c6ee8946491b698b067df2258e07918c25da02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6cbdb0cc3ddbb63499262cd3036882b08ee2690b", - "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c1c6ee8946491b698b067df2258e07918c25da02", + "reference": "c1c6ee8946491b698b067df2258e07918c25da02", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.1", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "php": ">=8.2", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^7.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.1|^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/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/filesystem": "^7.1", + "symfony/finder": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4", + "symfony/http-kernel": "^7.2", "symfony/polyfill-mbstring": "~1.0", "symfony/routing": "^6.4|^7.0" }, "conflict": { - "doctrine/annotations": "<1.13.1", "doctrine/persistence": "<1.3", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<5.4", + "symfony/asset": "<6.4", "symfony/asset-mapper": "<6.4", - "symfony/clock": "<6.3", - "symfony/console": "<5.4|>=7.0", + "symfony/clock": "<6.4", + "symfony/console": "<6.4", "symfony/dom-crawler": "<6.4", - "symfony/dotenv": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<6.3", - "symfony/lock": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<6.3", + "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": "<5.4", - "symfony/property-info": "<5.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/security-core": "<5.4", - "symfony/security-csrf": "<5.4", - "symfony/serializer": "<6.4", - "symfony/stopwatch": "<5.4", + "symfony/security-core": "<6.4", + "symfony/security-csrf": "<7.2", + "symfony/serializer": "<7.2.5", + "symfony/stopwatch": "<6.4", "symfony/translation": "<6.4", - "symfony/twig-bridge": "<5.4", - "symfony/twig-bundle": "<5.4", + "symfony/twig-bridge": "<6.4", + "symfony/twig-bundle": "<6.4", "symfony/validator": "<6.4", "symfony/web-profiler-bundle": "<6.4", + "symfony/webhook": "<7.2", "symfony/workflow": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.13.1|^2", "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": "^5.4|^6.0|^7.0", + "symfony/asset": "^6.4|^7.0", "symfony/asset-mapper": "^6.4|^7.0", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/clock": "^6.2|^7.0", - "symfony/console": "^5.4.9|^6.0.9|^7.0", - "symfony/css-selector": "^5.4|^6.0|^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": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/form": "^5.4|^6.0|^7.0", - "symfony/html-sanitizer": "^6.1|^7.0", - "symfony/http-client": "^6.3|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/mailer": "^5.4|^6.0|^7.0", - "symfony/messenger": "^6.3|^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": "^5.4|^6.0|^7.0", + "symfony/notifier": "^6.4|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.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.4|^7.0.4", - "symfony/security-bundle": "^5.4|^6.0|^7.0", - "symfony/semaphore": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/string": "^5.4|^6.0|^7.0", + "symfony/security-bundle": "^6.4|^7.0", + "symfony/semaphore": "^6.4|^7.0", + "symfony/serializer": "^7.2.5", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/type-info": "^7.1", + "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/webhook": "^7.2", "symfony/workflow": "^6.4|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0", - "twig/twig": "^2.10|^3.0.4" + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.12" }, "type": "symfony-bundle", "autoload": { @@ -4297,7 +4468,7 @@ "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/v6.4.10" + "source": "https://github.com/symfony/framework-bundle/tree/v7.2.5" }, "funding": [ { @@ -4313,45 +4484,60 @@ "type": "tidelift" } ], - "time": "2024-07-26T13:24:20+00:00" + "time": "2025-03-24T12:37:32+00:00" }, { - "name": "symfony/http-foundation", - "version": "v6.4.10", + "name": "symfony/http-client", + "version": "v7.2.4", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b" + "url": "https://github.com/symfony/http-client.git", + "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/117f1f20a7ade7bcea28b861fb79160a21a1e37b", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b", + "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", + "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/cache": "<6.3" + "amphp/amp": "<2.5", + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0" + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" + "Symfony\\Component\\HttpClient\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -4363,18 +4549,21 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Defines an object-oriented layer for the HTTP specification", + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", + "keywords": [ + "http" + ], "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.10" + "source": "https://github.com/symfony/http-client/tree/v7.2.4" }, "funding": [ { @@ -4390,77 +4579,233 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:36:27+00:00" + "time": "2025-02-13T10:27:23+00:00" }, { - "name": "symfony/http-kernel", - "version": "v6.4.10", + "name": "symfony/http-client-contracts", + "version": "v3.5.2", "source": { "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "147e0daf618d7575b5007055340d09aece5cf068" + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/147e0daf618d7575b5007055340d09aece5cf068", - "reference": "147e0daf618d7575b5007055340d09aece5cf068", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/polyfill-ctype": "^1.8" + "php": ">=8.1" }, - "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.4", - "symfony/config": "<6.1", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<5.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/translation": "<5.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<5.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.3", - "twig/twig": "<2.13" + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/clock": "^6.2|^7.0", - "symfony/config": "^6.1|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", + "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 HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.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": "2024-12-07T08:49:48+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b", + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^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.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-09T08:14:01+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^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.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/property-access": "^5.4.5|^6.0.5|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4.4|^7.0.4", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.4|^7.0", - "symfony/var-exporter": "^6.2|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" }, "type": "library", "autoload": { @@ -4488,7 +4833,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.10" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.6" }, "funding": [ { @@ -4504,29 +4849,32 @@ "type": "tidelift" } ], - "time": "2024-07-26T14:52:04+00:00" + "time": "2025-05-02T09:04:03+00:00" }, { "name": "symfony/intl", - "version": "v6.4.8", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb" + "reference": "f8a603f978b035d3a1dc23977fc8ae57558177ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/50265cdcf5a44bec3fcf487b5d0015aece91d1eb", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb", + "url": "https://api.github.com/repos/symfony/intl/zipball/f8a603f978b035d3a1dc23977fc8ae57558177ad", + "reference": "f8a603f978b035d3a1dc23977fc8ae57558177ad", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/string": "<7.1" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4571,7 +4919,91 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.8" + "source": "https://github.com/symfony/intl/tree/v7.2.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-07T19:09:28+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1", + "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.2.6" }, "funding": [ { @@ -4587,24 +5019,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -4638,7 +5070,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.8" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -4654,31 +5086,31 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31" + "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/90ebbe946e5d64a5fad9ac9427e335045cf2bd31", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", + "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "conflict": { - "symfony/security-core": "<5.4" + "symfony/security-core": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/security-core": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4710,7 +5142,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.8" + "source": "https://github.com/symfony/password-hasher/tree/v7.2.0" }, "funding": [ { @@ -4726,24 +5158,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -4751,8 +5183,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4788,7 +5220,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -4804,24 +5236,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.30.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "e76343c631b453088e2260ac41dfebe21954de81" + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e76343c631b453088e2260ac41dfebe21954de81", - "reference": "e76343c631b453088e2260ac41dfebe21954de81", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/763d2a91fea5681509ca01acbc1c5e450d127811", + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance and support of other locales than \"en\"" @@ -4829,8 +5261,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4872,7 +5304,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.32.0" }, "funding": [ { @@ -4888,24 +5320,25 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-12-21T18:38:29+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "name": "symfony/polyfill-intl-idn", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" @@ -4913,8 +5346,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4922,11 +5355,8 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4934,26 +5364,30 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "idn", "intl", - "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -4969,36 +5403,33 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" + "php": ">=7.2" }, "suggest": { - "ext-mbstring": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -5006,8 +5437,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5023,17 +5457,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "intl", + "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -5049,30 +5484,111 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php83", - "version": "v1.30.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", - "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -5109,7 +5625,83 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "000df7860439609837bbe28670b0be15783b7fbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/000df7860439609837bbe28670b0be15783b7fbf", + "reference": "000df7860439609837bbe28670b0be15783b7fbf", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.32.0" }, "funding": [ { @@ -5125,24 +5717,24 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:35:24+00:00" + "time": "2025-02-20T12:04:08+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.30.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9" + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/2ba1f33797470debcda07fe9dce20a0003df18e9", - "reference": "2ba1f33797470debcda07fe9dce20a0003df18e9", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -5153,8 +5745,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -5188,7 +5780,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" }, "funding": [ { @@ -5204,29 +5796,28 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/property-access", - "version": "v6.4.8", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "e4d9b00983612f9c0013ca37c61affdba2dd975a" + "reference": "b28732e315d81fbec787f838034de7d6c9b2b902" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/e4d9b00983612f9c0013ca37c61affdba2dd975a", - "reference": "e4d9b00983612f9c0013ca37c61affdba2dd975a", + "url": "https://api.github.com/repos/symfony/property-access/zipball/b28732e315d81fbec787f838034de7d6c9b2b902", + "reference": "b28732e315d81fbec787f838034de7d6c9b2b902", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/property-info": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/property-info": "^6.4|^7.0" }, "require-dev": { - "symfony/cache": "^5.4|^6.0|^7.0" + "symfony/cache": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5265,7 +5856,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.4.8" + "source": "https://github.com/symfony/property-access/tree/v7.2.3" }, "funding": [ { @@ -5281,37 +5872,39 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-01-17T10:56:55+00:00" }, { "name": "symfony/property-info", - "version": "v6.4.10", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77" + "reference": "f00fd9685ecdbabe82ca25c7b739ce7bba99302c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", - "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", + "url": "https://api.github.com/repos/symfony/property-info/zipball/f00fd9685ecdbabe82ca25c7b739ce7bba99302c", + "reference": "f00fd9685ecdbabe82ca25c7b739ce7bba99302c", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/string": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/string": "^6.4|^7.0", + "symfony/type-info": "~7.1.9|^7.2.2" }, "conflict": { "phpdocumentor/reflection-docblock": "<5.2", "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<5.4", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", "symfony/serializer": "<6.4" }, "require-dev": { "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0" }, "type": "library", @@ -5348,7 +5941,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.10" + "source": "https://github.com/symfony/property-info/tree/v7.2.5" }, "funding": [ { @@ -5364,40 +5957,38 @@ "type": "tidelift" } ], - "time": "2024-07-26T07:32:07+00:00" + "time": "2025-03-06T16:27:19+00:00" }, { "name": "symfony/routing", - "version": "v6.4.10", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87" + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/aad19fe10753ba842f0d653a8db819c4b3affa87", - "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87", + "url": "https://api.github.com/repos/symfony/routing/zipball/ee9a67edc6baa33e5fae662f94f91fd262930996", + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "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": { @@ -5431,7 +6022,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.10" + "source": "https://github.com/symfony/routing/tree/v7.2.3" }, "funding": [ { @@ -5447,35 +6038,35 @@ "type": "tidelift" } ], - "time": "2024-07-15T09:26:24+00:00" + "time": "2025-01-17T10:56:55+00:00" }, { "name": "symfony/runtime", - "version": "v6.4.8", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "b4bfa2fd4cad1fee62f80b3dfe4eb674cc3302a0" + "reference": "8e8d09bd69b7f6c0260dd3d58f37bd4fbdeab5ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/b4bfa2fd4cad1fee62f80b3dfe4eb674cc3302a0", - "reference": "b4bfa2fd4cad1fee62f80b3dfe4eb674cc3302a0", + "url": "https://api.github.com/repos/symfony/runtime/zipball/8e8d09bd69b7f6c0260dd3d58f37bd4fbdeab5ad", + "reference": "8e8d09bd69b7f6c0260dd3d58f37bd4fbdeab5ad", "shasum": "" }, "require": { "composer-plugin-api": "^1.0|^2.0", - "php": ">=8.1" + "php": ">=8.2" }, "conflict": { - "symfony/dotenv": "<5.4" + "symfony/dotenv": "<6.4" }, "require-dev": { - "composer/composer": "^1.0.2|^2.0", - "symfony/console": "^5.4.9|^6.0.9|^7.0", - "symfony/dotenv": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0" + "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": { @@ -5510,7 +6101,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.8" + "source": "https://github.com/symfony/runtime/tree/v7.2.3" }, "funding": [ { @@ -5526,75 +6117,69 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-12-29T21:39:47+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.4.10", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "50007f4f76632741b62fa9604c5f65807f268b72" + "reference": "721de227035c6e4c322fb7dd4839586d58bc0cf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/50007f4f76632741b62fa9604c5f65807f268b72", - "reference": "50007f4f76632741b62fa9604c5f65807f268b72", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/721de227035c6e4c322fb7dd4839586d58bc0cf5", + "reference": "721de227035c6e4c322fb7dd4839586d58bc0cf5", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.1", - "symfony/clock": "^6.3|^7.0", - "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.2|^7.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.2|^7.0", - "symfony/http-kernel": "^6.2", - "symfony/password-hasher": "^5.4|^6.0|^7.0", - "symfony/security-core": "^6.2|^7.0", - "symfony/security-csrf": "^5.4|^6.0|^7.0", - "symfony/security-http": "^6.3.6|^7.0", + "php": ">=8.2", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.11|^7.1.4", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/password-hasher": "^6.4|^7.0", + "symfony/security-core": "^7.2", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/security-http": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/console": "<5.4", + "symfony/browser-kit": "<6.4", + "symfony/console": "<6.4", "symfony/framework-bundle": "<6.4", - "symfony/http-client": "<5.4", - "symfony/ldap": "<5.4", + "symfony/http-client": "<6.4", + "symfony/ldap": "<6.4", "symfony/serializer": "<6.4", - "symfony/twig-bundle": "<5.4", + "symfony/twig-bundle": "<6.4", "symfony/validator": "<6.4" }, "require-dev": { - "symfony/asset": "^5.4|^6.0|^7.0", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/dom-crawler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/form": "^5.4|^6.0|^7.0", + "symfony/asset": "^6.4|^7.0", + "symfony/browser-kit": "^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/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/ldap": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/ldap": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", - "symfony/twig-bridge": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4", - "web-token/jwt-checker": "^3.1", - "web-token/jwt-signature-algorithm-ecdsa": "^3.1", - "web-token/jwt-signature-algorithm-eddsa": "^3.1", - "web-token/jwt-signature-algorithm-hmac": "^3.1", - "web-token/jwt-signature-algorithm-none": "^3.1", - "web-token/jwt-signature-algorithm-rsa": "^3.1" + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.12", + "web-token/jwt-library": "^3.3.2|^4.0" }, "type": "symfony-bundle", "autoload": { @@ -5622,7 +6207,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.10" + "source": "https://github.com/symfony/security-bundle/tree/v7.2.3" }, "funding": [ { @@ -5638,48 +6223,49 @@ "type": "tidelift" } ], - "time": "2024-07-17T10:49:44+00:00" + "time": "2025-01-07T09:39:55+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "432dec55da108c471adcf58c351af01372a52164" + "reference": "340e120d26b3bf5eee5cea0782aebaa2f36b6722" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/432dec55da108c471adcf58c351af01372a52164", - "reference": "432dec55da108c471adcf58c351af01372a52164", + "url": "https://api.github.com/repos/symfony/security-core/zipball/340e120d26b3bf5eee5cea0782aebaa2f36b6722", + "reference": "340e120d26b3bf5eee5cea0782aebaa2f36b6722", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/password-hasher": "^5.4|^6.0|^7.0", + "symfony/password-hasher": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/event-dispatcher": "<5.4", - "symfony/http-foundation": "<5.4", - "symfony/ldap": "<5.4", - "symfony/security-guard": "<5.4", - "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", - "symfony/validator": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/ldap": "<6.4", + "symfony/translation": "<6.4.3|>=7.0,<7.0.3", + "symfony/validator": "<6.4" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "psr/container": "^1.1|^2.0", "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/ldap": "^5.4|^6.0|^7.0", - "symfony/string": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/ldap": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^6.4.3|^7.0.3", "symfony/validator": "^6.4|^7.0" }, "type": "library", @@ -5708,7 +6294,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.10" + "source": "https://github.com/symfony/security-core/tree/v7.2.6" }, "funding": [ { @@ -5724,31 +6310,33 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-04-17T08:47:02+00:00" }, { "name": "symfony/security-csrf", - "version": "v6.4.8", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "f46ab02b76311087873257071559edcaf6d7ab99" + "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/f46ab02b76311087873257071559edcaf6d7ab99", - "reference": "f46ab02b76311087873257071559edcaf6d7ab99", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/2b4b0c46c901729e4e90719eacd980381f53e0a3", + "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/security-core": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/security-core": "^6.4|^7.0" }, "conflict": { - "symfony/http-foundation": "<5.4" + "symfony/http-foundation": "<6.4" }, "require-dev": { - "symfony/http-foundation": "^5.4|^6.0|^7.0" + "psr/log": "^1|^2|^3", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5776,7 +6364,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.4.8" + "source": "https://github.com/symfony/security-csrf/tree/v7.2.3" }, "funding": [ { @@ -5792,51 +6380,51 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-01-02T18:42:10+00:00" }, { "name": "symfony/security-http", - "version": "v6.4.9", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "8e70f39626ada36c5492c3aff9369c85d2840948" + "reference": "324425deb859c6a59a2c2414ae60f742976a193b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/8e70f39626ada36c5492c3aff9369c85d2840948", - "reference": "8e70f39626ada36c5492c3aff9369c85d2840948", + "url": "https://api.github.com/repos/symfony/security-http/zipball/324425deb859c6a59a2c2414ae60f742976a193b", + "reference": "324425deb859c6a59a2c2414ae60f742976a193b", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-foundation": "^6.2|^7.0", - "symfony/http-kernel": "^6.3|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^5.4|^6.0|^7.0", - "symfony/security-core": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/security-core": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/clock": "<6.3", - "symfony/event-dispatcher": "<5.4.9|>=6,<6.0.9", + "symfony/clock": "<6.4", + "symfony/event-dispatcher": "<6.4", "symfony/http-client-contracts": "<3.0", - "symfony/security-bundle": "<5.4", - "symfony/security-csrf": "<5.4" + "symfony/security-bundle": "<6.4", + "symfony/security-csrf": "<6.4" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/clock": "^6.3|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/cache": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", "symfony/http-client-contracts": "^3.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/security-csrf": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", - "web-token/jwt-checker": "^3.1", - "web-token/jwt-signature-algorithm-ecdsa": "^3.1" + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "web-token/jwt-library": "^3.3.2|^4.0" }, "type": "library", "autoload": { @@ -5864,7 +6452,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.9" + "source": "https://github.com/symfony/security-http/tree/v7.2.6" }, "funding": [ { @@ -5880,20 +6468,20 @@ "type": "tidelift" } ], - "time": "2024-06-21T16:04:15+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -5906,12 +6494,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -5947,7 +6535,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -5963,24 +6551,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.8", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "63e069eb616049632cde9674c46957819454b8aa" + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/63e069eb616049632cde9674c46957819454b8aa", - "reference": "63e069eb616049632cde9674c46957819454b8aa", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -6009,7 +6597,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.8" + "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" }, "funding": [ { @@ -6025,24 +6613,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-02-24T10:49:57+00:00" }, { "name": "symfony/string", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ccf9b30251719567bfd46494138327522b9a9446" + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ccf9b30251719567bfd46494138327522b9a9446", - "reference": "ccf9b30251719567bfd46494138327522b9a9446", + "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -6052,11 +6640,12 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6095,7 +6684,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.10" + "source": "https://github.com/symfony/string/tree/v7.2.6" }, "funding": [ { @@ -6111,37 +6700,37 @@ "type": "tidelift" } ], - "time": "2024-07-22T10:21:14+00:00" + "time": "2025-04-20T20:18:16+00:00" }, { "name": "symfony/translation", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9" + "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/94041203f8ac200ae9e7c6a18fa6137814ccecc9", - "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9", + "url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", + "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", + "symfony/http-kernel": "<6.4", "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" @@ -6149,17 +6738,17 @@ "require-dev": { "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "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/finder": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/routing": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6190,7 +6779,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.10" + "source": "https://github.com/symfony/translation/tree/v7.2.6" }, "funding": [ { @@ -6206,20 +6795,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { @@ -6227,12 +6816,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -6268,7 +6857,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -6284,69 +6873,70 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.9", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "9bcb26445b9d4ef1087c389234bf33fb00e10ea6" + "reference": "b1942d5515b7f0a18e16fd668a04ea952db2b0f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9bcb26445b9d4ef1087c389234bf33fb00e10ea6", - "reference": "9bcb26445b9d4ef1087c389234bf33fb00e10ea6", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/b1942d5515b7f0a18e16fd668a04ea952db2b0f2", + "reference": "b1942d5515b7f0a18e16fd668a04ea952db2b0f2", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/translation-contracts": "^2.5|^3", - "twig/twig": "^2.13|^3.0.4" + "twig/twig": "^3.12" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<5.4", - "symfony/form": "<6.3", - "symfony/http-foundation": "<5.4", + "symfony/console": "<6.4", + "symfony/form": "<6.4", + "symfony/http-foundation": "<6.4", "symfony/http-kernel": "<6.4", - "symfony/mime": "<6.2", + "symfony/mime": "<6.4", "symfony/serializer": "<6.4", - "symfony/translation": "<5.4", - "symfony/workflow": "<5.4" + "symfony/translation": "<6.4", + "symfony/workflow": "<6.4" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0|^7.0", - "symfony/asset-mapper": "^6.3|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.1|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/emoji": "^7.1", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/form": "^6.4.20|^7.2.5", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", - "symfony/mime": "^6.2|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^5.4|^6.0|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^5.4|^6.0|^7.0", - "symfony/security-csrf": "^5.4|^6.0|^7.0", - "symfony/security-http": "^5.4|^6.0|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/security-http": "^6.4|^7.0", "symfony/serializer": "^6.4.3|^7.0.3", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/translation": "^6.1|^7.0", - "symfony/web-link": "^5.4|^6.0|^7.0", - "symfony/workflow": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", "twig/cssinliner-extra": "^2.12|^3", "twig/inky-extra": "^2.12|^3", "twig/markdown-extra": "^2.12|^3" @@ -6377,7 +6967,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.9" + "source": "https://github.com/symfony/twig-bridge/tree/v7.2.5" }, "funding": [ { @@ -6393,47 +6983,47 @@ "type": "tidelift" } ], - "time": "2024-06-21T16:04:15+00:00" + "time": "2025-03-28T13:15:09+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "ef17bc8fc2cb2376b235cd1b98f0275a78c5ba65" + "reference": "cd2be4563afaef5285bb6e0a06c5445e644a5c01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/ef17bc8fc2cb2376b235cd1b98f0275a78c5ba65", - "reference": "ef17bc8fc2cb2376b235cd1b98f0275a78c5ba65", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/cd2be4563afaef5285bb6e0a06c5445e644a5c01", + "reference": "cd2be4563afaef5285bb6e0a06c5445e644a5c01", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", - "php": ">=8.1", - "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.1|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^6.2", - "symfony/twig-bridge": "^6.4", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "symfony/framework-bundle": "<5.4", - "symfony/translation": "<5.4" - }, + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "conflict": { + "symfony/framework-bundle": "<6.4", + "symfony/translation": "<6.4" + }, "require-dev": { - "symfony/asset": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^5.4|^6.0|^7.0", - "symfony/framework-bundle": "^5.4|^6.0|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", - "symfony/web-link": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/asset": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -6461,7 +7051,82 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/twig-bundle/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-23T08:11:15+00:00" + }, + { + "name": "symfony/type-info", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "c4824a6b658294c828e609d3d8dbb4e87f6a375d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/c4824a6b658294c828e609d3d8dbb4e87f6a375d", + "reference": "c4824a6b658294c828e609d3d8dbb4e87f6a375d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.0|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.2.5" }, "funding": [ { @@ -6477,28 +7142,28 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-03-24T09:03:36+00:00" }, { "name": "symfony/uid", - "version": "v6.4.8", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "35904eca37a84bb764c560cbfcac9f0ac2bcdbdf" + "reference": "2d294d0c48df244c71c105a169d0190bfb080426" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/35904eca37a84bb764c560cbfcac9f0ac2bcdbdf", - "reference": "35904eca37a84bb764c560cbfcac9f0ac2bcdbdf", + "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6535,7 +7200,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.8" + "source": "https://github.com/symfony/uid/tree/v7.2.0" }, "funding": [ { @@ -6551,24 +7216,107 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/ux-twig-component", + "version": "v2.25.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/ux-twig-component.git", + "reference": "d20da25517fc09d147897d02819a046f0a0f6735" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/d20da25517fc09d147897d02819a046f0a0f6735", + "reference": "d20da25517fc09d147897d02819a046f0a0f6735", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^2.2|^3.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "twig/twig": "^3.10.3" + }, + "conflict": { + "symfony/config": "<5.4.0" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^6.0|^7.0", + "symfony/stimulus-bundle": "^2.9.1", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/webpack-encore-bundle": "^1.15" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/symfony/ux", + "name": "symfony/ux" + } + }, + "autoload": { + "psr-4": { + "Symfony\\UX\\TwigComponent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Twig components for Symfony", + "homepage": "https://symfony.com", + "keywords": [ + "components", + "symfony-ux", + "twig" + ], + "support": { + "source": "https://github.com/symfony/ux-twig-component/tree/v2.25.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": "2025-05-20T13:06:01+00:00" }, { "name": "symfony/validator", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd" + "reference": "f7c32e309885a97fc9572335e22c2c2d31f328c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd", - "reference": "bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd", + "url": "https://api.github.com/repos/symfony/validator/zipball/f7c32e309885a97fc9572335e22c2c2d31f328c4", + "reference": "f7c32e309885a97fc9572335e22c2c2d31f328c4", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", @@ -6576,34 +7324,34 @@ "symfony/translation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.13", "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<5.4", - "symfony/expression-language": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/intl": "<5.4", - "symfony/property-info": "<5.4", - "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", - "symfony/yaml": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<7.0", + "symfony/expression-language": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/intl": "<6.4", + "symfony/property-info": "<6.4", + "symfony/translation": "<6.4.3|>=7.0,<7.0.3", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.13|^2", "egulias/email-validator": "^2.1.10|^3|^4", - "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/expression-language": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/property-access": "^5.4|^6.0|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/translation": "^6.4.3|^7.0.3", + "symfony/type-info": "^7.1", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6632,7 +7380,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.10" + "source": "https://github.com/symfony/validator/tree/v7.2.6" }, "funding": [ { @@ -6648,38 +7396,36 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-05-02T08:36:00+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.10", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4" + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a71cc3374f5fb9759da1961d28c452373b343dd4", - "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb", + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -6717,7 +7463,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.10" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.6" }, "funding": [ { @@ -6733,30 +7479,29 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-04-09T08:14:01+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.9", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e" + "reference": "422b8de94c738830a1e071f59ad14d67417d7007" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9a060622e0d93777b7f8687ec4860191e16802e", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007", + "reference": "422b8de94c738830a1e071f59ad14d67417d7007", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2" }, "require-dev": { "symfony/property-access": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6794,7 +7539,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.9" + "source": "https://github.com/symfony/var-exporter/tree/v7.2.6" }, "funding": [ { @@ -6810,32 +7555,32 @@ "type": "tidelift" } ], - "time": "2024-06-24T15:53:56+00:00" + "time": "2025-05-02T08:36:00+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.8", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9" + "reference": "0feafffb843860624ddfd13478f481f4c3cd8b23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/52903de178d542850f6f341ba92995d3d63e60c9", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0feafffb843860624ddfd13478f481f4c3cd8b23", + "reference": "0feafffb843860624ddfd13478f481f4c3cd8b23", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -6866,7 +7611,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.8" + "source": "https://github.com/symfony/yaml/tree/v7.2.6" }, "funding": [ { @@ -6882,49 +7627,51 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-04-04T10:10:11+00:00" }, { - "name": "twig/twig", - "version": "v3.11.0", + "name": "twig/extra-bundle", + "version": "v3.21.0", "source": { "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d" + "url": "https://github.com/twigphp/twig-extra-bundle.git", + "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", - "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/62d1cf47a1aa009cbd07b21045b97d3d5cb79896", + "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22", - "symfony/polyfill-php81": "^1.29" + "php": ">=8.1.0", + "symfony/framework-bundle": "^5.4|^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.4|^7.0", + "twig/twig": "^3.2|^4.0" }, "require-dev": { - "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" + "league/commonmark": "^1.0|^2.0", + "symfony/phpunit-bridge": "^6.4|^7.0", + "twig/cache-extra": "^3.0", + "twig/cssinliner-extra": "^3.0", + "twig/html-extra": "^3.0", + "twig/inky-extra": "^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.0", + "twig/string-extra": "^3.0" }, - "type": "library", + "type": "symfony-bundle", "autoload": { - "files": [ - "src/Resources/core.php", - "src/Resources/debug.php", - "src/Resources/escaper.php", - "src/Resources/string_loader.php" - ], "psr-4": { - "Twig\\": "src/" - } + "Twig\\Extra\\TwigExtraBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { @@ -6932,25 +7679,17 @@ "email": "fabien@symfony.com", "homepage": "http://fabien.potencier.org", "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" } ], - "description": "Twig, the flexible, fast, and secure template language for PHP", + "description": "A Symfony bundle for extra Twig extensions", "homepage": "https://twig.symfony.com", "keywords": [ - "templating" + "bundle", + "extra", + "twig" ], "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.11.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.21.0" }, "funding": [ { @@ -6962,37 +7701,42 @@ "type": "tidelift" } ], - "time": "2024-08-08T16:15:16+00:00" - } - ], - "packages-dev": [ + "time": "2025-02-19T14:29:33+00:00" + }, { - "name": "clue/ndjson-react", - "version": "v1.3.0", + "name": "twig/html-extra", + "version": "v3.21.0", "source": { "type": "git", - "url": "https://github.com/clue/reactphp-ndjson.git", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + "url": "https://github.com/twigphp/html-extra.git", + "reference": "5442dd707601c83b8cd4233e37bb10ab8489a90f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "url": "https://api.github.com/repos/twigphp/html-extra/zipball/5442dd707601c83b8cd4233e37bb10ab8489a90f", + "reference": "5442dd707601c83b8cd4233e37bb10ab8489a90f", "shasum": "" }, "require": { - "php": ">=5.3", - "react/stream": "^1.2" + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/mime": "^5.4|^6.4|^7.0", + "twig/twig": "^3.13|^4.0" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", - "react/event-loop": "^1.2" + "symfony/phpunit-bridge": "^6.4|^7.0" }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Clue\\React\\NDJson\\": "src/" - } + "Twig\\Extra\\Html\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7000,76 +7744,64 @@ ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering" + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], - "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", - "homepage": "https://github.com/clue/reactphp-ndjson", + "description": "A Twig extension for HTML", + "homepage": "https://twig.symfony.com", "keywords": [ - "NDJSON", - "json", - "jsonlines", - "newline", - "reactphp", - "streaming" + "html", + "twig" ], "support": { - "issues": "https://github.com/clue/reactphp-ndjson/issues", - "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + "source": "https://github.com/twigphp/html-extra/tree/v3.21.0" }, "funding": [ { - "url": "https://clue.engineering/support", - "type": "custom" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://github.com/clue", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" } ], - "time": "2022-12-23T10:58:28+00:00" + "time": "2025-02-19T14:29:33+00:00" }, { - "name": "composer/pcre", - "version": "3.3.1", + "name": "twig/string-extra", + "version": "v3.21.0", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" + "url": "https://github.com/twigphp/string-extra.git", + "reference": "4b3337544ac8f76c280def94e32b53acfaec0589" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", - "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "url": "https://api.github.com/repos/twigphp/string-extra/zipball/4b3337544ac8f76c280def94e32b53acfaec0589", + "reference": "4b3337544ac8f76c280def94e32b53acfaec0589", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" + "php": ">=8.1.0", + "symfony/string": "^5.4|^6.4|^7.0", + "symfony/translation-contracts": "^1.1|^2|^3", + "twig/twig": "^3.13|^4.0" }, "require-dev": { - "phpstan/phpstan": "^1.11.10", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8 || ^9" + "symfony/phpunit-bridge": "^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, "autoload": { "psr-4": { - "Composer\\Pcre\\": "src" - } + "Twig\\Extra\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7077,68 +7809,142 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "description": "A Twig extension for Symfony String", + "homepage": "https://twig.symfony.com", "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" + "html", + "string", + "twig", + "unicode" ], "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.1" + "source": "https://github.com/twigphp/string-extra/tree/v3.21.0" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/twig/twig", "type": "tidelift" } ], - "time": "2024-08-27T18:44:43+00:00" + "time": "2025-01-31T20:45:36+00:00" }, { - "name": "composer/semver", - "version": "3.4.2", + "name": "twig/twig", + "version": "v3.21.1", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" + "url": "https://github.com/twigphp/Twig.git", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^2.0", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" + "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], + "psr-4": { + "Twig\\": "src/" } }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2025-05-03T07:21:55+00:00" + } + ], + "packages-dev": [ + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "Clue\\React\\NDJson\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -7147,48 +7953,35 @@ ], "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": "Christian Lück", + "email": "christian@clue.engineering" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" ], "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.2" + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" }, "funding": [ { - "url": "https://packagist.com", + "url": "https://clue.engineering/support", "type": "custom" }, { - "url": "https://github.com/composer", + "url": "https://github.com/clue", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-07-12T11:35:52+00:00" + "time": "2022-12-23T10:58:28+00:00" }, { "name": "composer/xdebug-handler", @@ -7258,49 +8051,55 @@ }, { "name": "ergebnis/composer-normalize", - "version": "2.43.0", + "version": "2.47.0", "source": { "type": "git", "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "4b46330c84bb8f43fac79f5c5a05162fc7c80d75" + "reference": "ed24b9f8901f8fbafeca98f662eaca39427f0544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/4b46330c84bb8f43fac79f5c5a05162fc7c80d75", - "reference": "4b46330c84bb8f43fac79f5c5a05162fc7c80d75", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/ed24b9f8901f8fbafeca98f662eaca39427f0544", + "reference": "ed24b9f8901f8fbafeca98f662eaca39427f0544", "shasum": "" }, "require": { "composer-plugin-api": "^2.0.0", - "ergebnis/json": "^1.2.0", - "ergebnis/json-normalizer": "^4.5.0", - "ergebnis/json-printer": "^3.5.0", + "ergebnis/json": "^1.4.0", + "ergebnis/json-normalizer": "^4.9.0", + "ergebnis/json-printer": "^3.7.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "localheinz/diff": "^1.1.1", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "localheinz/diff": "^1.2.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "composer/composer": "^2.7.7", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.30.1", - "ergebnis/phpunit-slow-test-detector": "^2.14.0", - "fakerphp/faker": "^1.23.1", + "composer/composer": "^2.8.3", + "ergebnis/license": "^2.6.0", + "ergebnis/php-cs-fixer-config": "^6.46.0", + "ergebnis/phpunit-slow-test-detector": "^2.19.1", + "fakerphp/faker": "^1.24.1", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.1.0", - "symfony/filesystem": "^5.4.40", - "vimeo/psalm": "^5.24.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.11", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.6", + "phpstan/phpstan-strict-rules": "^2.0.4", + "phpunit/phpunit": "^9.6.20", + "rector/rector": "^2.0.11", + "symfony/filesystem": "^5.4.41" }, "type": "composer-plugin", "extra": { "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", + "branch-alias": { + "dev-main": "2.44-dev" + }, + "plugin-optional": true, "composer-normalize": { "indent-size": 2, "indent-style": "space" - }, - "plugin-optional": true + } }, "autoload": { "psr-4": { @@ -7331,37 +8130,40 @@ "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2024-06-16T13:22:18+00:00" + "time": "2025-04-15T11:09:27+00:00" }, { "name": "ergebnis/json", - "version": "1.2.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json.git", - "reference": "a457f25a5ba7ea11fc94f84d53678c5211abfce0" + "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json/zipball/a457f25a5ba7ea11fc94f84d53678c5211abfce0", - "reference": "a457f25a5ba7ea11fc94f84d53678c5211abfce0", + "url": "https://api.github.com/repos/ergebnis/json/zipball/7656ac2aa6c2ca4408f96f599e9a17a22c464f69", + "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69", "shasum": "" }, "require": { "ext-json": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.20.0", - "ergebnis/phpunit-slow-test-detector": "^2.9.0", - "fakerphp/faker": "^1.23.1", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.19.2", - "vimeo/psalm": "^5.20.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.18", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { @@ -7396,20 +8198,20 @@ "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json" }, - "time": "2024-01-29T15:09:24+00:00" + "time": "2024-11-17T11:51:22+00:00" }, { "name": "ergebnis/json-normalizer", - "version": "4.5.0", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-normalizer.git", - "reference": "f0ee9e70739f121b27fac8b743e4a52b23de2152" + "reference": "cc4dcf3890448572a2d9bea97133c4d860e59fb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/f0ee9e70739f121b27fac8b743e4a52b23de2152", - "reference": "f0ee9e70739f121b27fac8b743e4a52b23de2152", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/cc4dcf3890448572a2d9bea97133c4d860e59fb1", + "reference": "cc4dcf3890448572a2d9bea97133c4d860e59fb1", "shasum": "" }, "require": { @@ -7418,26 +8220,39 @@ "ergebnis/json-printer": "^3.5.0", "ergebnis/json-schema-validator": "^4.2.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "composer/semver": "^3.4.0", - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.20.0", - "ergebnis/phpunit-slow-test-detector": "^2.9.0", - "fakerphp/faker": "^1.23.1", + "composer/semver": "^3.4.3", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.19.4", - "vimeo/psalm": "^5.20.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.19", + "rector/rector": "^1.2.10" }, "suggest": { "composer/semver": "If you want to use ComposerJsonNormalizer or VersionConstraintNormalizer" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.8-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { "psr-4": { "Ergebnis\\Json\\Normalizer\\": "src/" @@ -7465,39 +8280,46 @@ "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-normalizer" }, - "time": "2024-01-30T09:10:15+00:00" + "time": "2025-04-10T13:13:04+00:00" }, { "name": "ergebnis/json-pointer", - "version": "3.4.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-pointer.git", - "reference": "b654757d873050622c2166f55ab25d04685261c5" + "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/b654757d873050622c2166f55ab25d04685261c5", - "reference": "b654757d873050622c2166f55ab25d04685261c5", + "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/4fc85d8edb74466d282119d8d9541ec7cffc0798", + "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798", "shasum": "" }, "require": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { + "ergebnis/composer-normalize": "^2.43.0", "ergebnis/data-provider": "^3.2.0", "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.20.0", - "ergebnis/phpunit-slow-test-detector": "^2.9.0", + "ergebnis/php-cs-fixer-config": "^6.32.0", + "ergebnis/phpunit-slow-test-detector": "^2.15.0", "fakerphp/faker": "^1.23.1", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.19.2", - "vimeo/psalm": "^5.20.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.19", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "3.6-dev" + }, "composer-normalize": { "indent-size": 2, "indent-style": "space" @@ -7531,38 +8353,41 @@ "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-pointer" }, - "time": "2024-01-29T16:37:15+00:00" + "time": "2024-11-17T12:37:06+00:00" }, { "name": "ergebnis/json-printer", - "version": "3.5.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-printer.git", - "reference": "549e16fe6de34b8c3aee7b421be12caa552f3ced" + "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/549e16fe6de34b8c3aee7b421be12caa552f3ced", - "reference": "549e16fe6de34b8c3aee7b421be12caa552f3ced", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/ced41fce7854152f0e8f38793c2ffe59513cdd82", + "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.20.0", - "ergebnis/phpunit-slow-test-detector": "^2.9.0", - "fakerphp/faker": "^1.23.1", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.19.2", - "vimeo/psalm": "^5.20.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.1", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.21", + "rector/rector": "^1.2.10" }, "type": "library", "autoload": { @@ -7593,43 +8418,50 @@ "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-printer" }, - "time": "2024-01-29T15:33:37+00:00" + "time": "2024-11-17T11:20:51+00:00" }, { "name": "ergebnis/json-schema-validator", - "version": "4.2.0", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-schema-validator.git", - "reference": "10ed514fdc3f9b71f8a92c567afea21a2f6fa1ef" + "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/10ed514fdc3f9b71f8a92c567afea21a2f6fa1ef", - "reference": "10ed514fdc3f9b71f8a92c567afea21a2f6fa1ef", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/85f90c81f718aebba1d738800af83eeb447dc7ec", + "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec", "shasum": "" }, "require": { "ergebnis/json": "^1.2.0", "ergebnis/json-pointer": "^3.4.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.20.0", - "ergebnis/phpunit-slow-test-detector": "^2.9.0", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.16", - "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.19.2", - "vimeo/psalm": "^5.20.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.20", + "rector/rector": "^1.2.10" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "4.4-dev" + }, "composer-normalize": { "indent-size": 2, "indent-style": "space" @@ -7663,7 +8495,7 @@ "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-schema-validator" }, - "time": "2024-01-29T16:50:15+00:00" + "time": "2024-11-18T06:32:28+00:00" }, { "name": "evenement/evenement", @@ -7775,16 +8607,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.66.0", + "version": "v3.75.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "5f5f2a142ff36b93c41885bca29cc5f861c013e6" + "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5f5f2a142ff36b93c41885bca29cc5f861c013e6", - "reference": "5f5f2a142ff36b93c41885bca29cc5f861c013e6", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c", + "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c", "shasum": "" }, "require": { @@ -7792,6 +8624,7 @@ "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.3", "ext-filter": "*", + "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", "fidry/cpu-core-counter": "^1.2", @@ -7801,31 +8634,31 @@ "react/promise": "^2.0 || ^3.0", "react/socket": "^1.0", "react/stream": "^1.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.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 <7.2", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", + "symfony/finder": "^5.4 || ^6.4 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", + "symfony/polyfill-mbstring": "^1.31", + "symfony/polyfill-php80": "^1.31", + "symfony/polyfill-php81": "^1.31", + "symfony/process": "^5.4 || ^6.4 || ^7.2", + "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.4", - "infection/infection": "^0.29.8", - "justinrainbow/json-schema": "^5.3 || ^6.0", + "facile-it/paraunit": "^1.3.1 || ^2.6", + "infection/infection": "^0.29.14", + "justinrainbow/json-schema": "^5.3 || ^6.2", "keradus/cli-executor": "^2.1", "mikey179/vfsstream": "^1.6.12", "php-coveralls/php-coveralls": "^2.7", "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", - "phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3", - "symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8", - "symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6" + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", + "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12", + "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3", + "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -7866,7 +8699,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.66.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0" }, "funding": [ { @@ -7874,34 +8707,44 @@ "type": "github" } ], - "time": "2024-12-29T13:46:23+00:00" + "time": "2025-03-31T18:40:42+00:00" }, { "name": "justinrainbow/json-schema", - "version": "5.3.0", + "version": "6.4.1", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/35d262c94959571e8736db1e5c9bc36ab94ae900", + "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-json": "*", + "marc-mabe/php-enum": "^4.0", + "php": "^7.2 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "friendsofphp/php-cs-fixer": "3.3.0", "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" }, "bin": [ "bin/validate-json" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" @@ -7930,134 +8773,380 @@ } ], "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", + "homepage": "https://github.com/jsonrainbow/json-schema", "keywords": [ "json", "schema" ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.1" }, - "time": "2024-07-06T21:00:26+00:00" + "time": "2025-04-04T13:08:07+00:00" }, { "name": "localheinz/diff", - "version": "1.1.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/localheinz/diff.git", - "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c" + "reference": "ec413943c2b518464865673fd5b38f7df867a010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/localheinz/diff/zipball/851bb20ea8358c86f677f5f111c4ab031b1c764c", - "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c", + "url": "https://api.github.com/repos/localheinz/diff/zipball/ec413943c2b518464865673fd5b38f7df867a010", + "reference": "ec413943c2b518464865673fd5b38f7df867a010", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", + "phpunit/phpunit": "^7.5.0 || ^8.5.23", "symfony/process": "^4.2 || ^5" }, "type": "library", "autoload": { - "classmap": [ - "src/" + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "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/localheinz/diff/issues", + "source": "https://github.com/localheinz/diff/tree/1.2.0" + }, + "time": "2024-12-04T14:16:01+00:00" + }, + { + "name": "marc-mabe/php-enum", + "version": "v4.7.1", + "source": { + "type": "git", + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "shasum": "" + }, + "require": { + "ext-reflection": "*", + "php": "^7.1 | ^8.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" + } + }, + "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" + }, + "time": "2024-11-28T04:54:44+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" + }, + "time": "2024-09-04T20:21:43+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.16", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "b8c1cf533cba0c305d91c6ccd23f3dd0566ba5f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b8c1cf533cba0c305d91c6ccd23f3dd0566ba5f9", + "reference": "b8c1cf533cba0c305d91c6ccd23f3dd0566ba5f9", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } + "MIT" ], - "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", - "homepage": "https://github.com/localheinz/diff", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" + "dev", + "static analysis" ], "support": { - "source": "https://github.com/localheinz/diff/tree/main" + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", "type": "github" } ], - "time": "2020-07-06T04:49:32+00:00" + "time": "2025-05-16T09:40:10+00:00" }, { - "name": "nikic/php-parser", - "version": "v5.1.0", + "name": "phpstan/phpstan-doctrine", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "url": "https://github.com/phpstan/phpstan-doctrine.git", + "reference": "4497663eb17b9d29211830df5aceaa3a4d256a35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/4497663eb17b9d29211830df5aceaa3a4d256a35", + "reference": "4497663eb17b9d29211830df5aceaa3a4d256a35", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.13" }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" + "conflict": { + "doctrine/collections": "<1.0", + "doctrine/common": "<2.7", + "doctrine/mongodb-odm": "<1.2", + "doctrine/orm": "<2.5", + "doctrine/persistence": "<1.3" }, - "bin": [ - "bin/php-parse" - ], - "type": "library", + "require-dev": { + "cache/array-adapter": "^1.1", + "composer/semver": "^3.3.2", + "cweagans/composer-patches": "^1.7.3", + "doctrine/annotations": "^2.0", + "doctrine/collections": "^1.6 || ^2.1", + "doctrine/common": "^2.7 || ^3.0", + "doctrine/dbal": "^3.3.8", + "doctrine/lexer": "^2.0 || ^3.0", + "doctrine/mongodb-odm": "^2.4.3", + "doctrine/orm": "^2.16.0", + "doctrine/persistence": "^2.2.1 || ^3.2", + "gedmo/doctrine-extensions": "^3.8", + "nesbot/carbon": "^2.49", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6.20", + "ramsey/uuid": "^4.2", + "symfony/cache": "^5.4" + }, + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "5.0-dev" + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" + "MIT" ], + "description": "Doctrine extensions for PHPStan", "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "issues": "https://github.com/phpstan/phpstan-doctrine/issues", + "source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.3" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2025-05-05T15:28:52+00:00" }, { "name": "react/cache", @@ -8133,33 +9222,33 @@ }, { "name": "react/child-process", - "version": "v0.6.5", + "version": "v0.6.6", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", - "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", "react/event-loop": "^1.2", - "react/stream": "^1.2" + "react/stream": "^1.4" }, "require-dev": { - "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", - "react/socket": "^1.8", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" }, "type": "library", "autoload": { "psr-4": { - "React\\ChildProcess\\": "src" + "React\\ChildProcess\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -8196,19 +9285,15 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + "source": "https://github.com/reactphp/child-process/tree/v0.6.6" }, "funding": [ { - "url": "https://github.com/WyriHaximus", - "type": "github" - }, - { - "url": "https://github.com/clue", - "type": "github" + "url": "https://opencollective.com/reactphp", + "type": "open_collective" } ], - "time": "2022-09-16T13:41:56+00:00" + "time": "2025-01-01T16:37:48+00:00" }, { "name": "react/dns", @@ -8589,31 +9674,90 @@ ], "time": "2024-06-11T12:45:25+00:00" }, + { + "name": "rector/rector", + "version": "2.0.16", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", + "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.14" + }, + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "suggest": { + "ext-dom": "To manipulate phpunit.xml via the custom-rule command" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" + ], + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/2.0.16" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2025-05-12T16:37:16+00:00" + }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "7ab1ea946c012266ca32390913653d844ecd085f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^12.0", + "symfony/process": "^7.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -8646,7 +9790,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" }, "funding": [ { @@ -8654,25 +9798,99 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2025-02-07T04:55:46+00:00" + }, + { + "name": "symfony/debug-bundle", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "2dade0d1415c08b627379b5ec214ec8424cb2e32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/2dade0d1415c08b627379b5ec214ec8424cb2e32", + "reference": "2dade0d1415c08b627379b5ec214ec8424cb2e32", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=8.2", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4" + }, + "require-dev": { + "symfony/config": "^6.4|^7.0", + "symfony/web-profiler-bundle": "^6.4|^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "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 of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug-bundle/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.60.0", + "version": "v1.63.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "c305a02a22974670f359d4274c9431e1a191f559" + "reference": "69478ab39bc303abfbe3293006a78b09a8512425" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c305a02a22974670f359d4274c9431e1a191f559", - "reference": "c305a02a22974670f359d4274c9431e1a191f559", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/69478ab39bc303abfbe3293006a78b09a8512425", + "reference": "69478ab39bc303abfbe3293006a78b09a8512425", "shasum": "" }, "require": { "doctrine/inflector": "^2.0", - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "php": ">=8.1", "symfony/config": "^6.4|^7.0", "symfony/console": "^6.4|^7.0", @@ -8730,7 +9948,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.60.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.63.0" }, "funding": [ { @@ -8746,20 +9964,20 @@ "type": "tidelift" } ], - "time": "2024-06-10T06:03:18+00:00" + "time": "2025-04-26T01:41:37+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.1.3", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1" + "reference": "6106ae85a0e3ed509d339b7f924788c9cc4e7cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/e823122d31935eb711e2767c31f3d71cb0b87fb1", - "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/6106ae85a0e3ed509d339b7f924788c9cc4e7cfb", + "reference": "6106ae85a0e3ed509d339b7f924788c9cc4e7cfb", "shasum": "" }, "require": { @@ -8779,8 +9997,8 @@ "type": "symfony-bridge", "extra": { "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { @@ -8812,7 +10030,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.1.3" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.2.6" }, "funding": [ { @@ -8828,24 +10046,24 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2025-04-09T08:35:42+00:00" }, { "name": "symfony/process", - "version": "v6.4.8", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5" + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8d92dd79149f29e89ee0f480254db595f6a6a2c5", - "reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5", + "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -8873,7 +10091,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.8" + "source": "https://github.com/symfony/process/tree/v7.2.5" }, "funding": [ { @@ -8889,42 +10107,42 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-03-13T12:21:46+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.10", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7" + "reference": "4ffde1c860a100533b02697d9aaf5f45759ec26a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/370c9f1e3567cd4670d44311838e37d16182c3a7", - "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4ffde1c860a100533b02697d9aaf5f45759ec26a", + "reference": "4ffde1c860a100533b02697d9aaf5f45759ec26a", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/config": "^5.4|^6.0|^7.0", + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", "symfony/framework-bundle": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/routing": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "twig/twig": "^3.12" }, "conflict": { - "symfony/form": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/twig-bundle": ">=7.0" + "symfony/form": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/serializer": "<7.2" }, "require-dev": { - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -8955,7 +10173,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.10" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.2.4" }, "funding": [ { @@ -8971,7 +10189,142 @@ "type": "tidelift" } ], - "time": "2024-07-19T07:26:48+00:00" + "time": "2025-02-14T14:27:24+00:00" + }, + { + "name": "vincentlanglet/twig-cs-fixer", + "version": "3.7.1", + "source": { + "type": "git", + "url": "https://github.com/VincentLanglet/Twig-CS-Fixer.git", + "reference": "d216db67b63d78cfdefca6a9a7acef4fd0d304bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/d216db67b63d78cfdefca6a9a7acef4fd0d304bb", + "reference": "d216db67b63d78cfdefca6a9a7acef4fd0d304bb", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "ext-ctype": "*", + "ext-json": "*", + "php": ">=8.0", + "symfony/console": "^5.4.9 || ^6.4 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", + "symfony/finder": "^5.4 || ^6.4 || ^7.0", + "symfony/string": "^5.4.42 || ^6.4.10 || ~7.0.10 || ^7.1.3", + "twig/twig": "^3.4", + "webmozart/assert": "^1.10" + }, + "require-dev": { + "composer/semver": "^3.2.0", + "dereuromark/composer-prefer-lowest": "^0.1.10", + "ergebnis/composer-normalize": "^2.29", + "friendsofphp/php-cs-fixer": "^3.13.0", + "infection/infection": "^0.26.16 || ^0.29.14", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", + "phpstan/phpstan-webmozart-assert": "^2.0", + "phpunit/phpunit": "^9.5.26 || ^11.5.18 || ^12.1.3", + "rector/rector": "^2.0.0", + "shipmonk/composer-dependency-analyser": "^1.6", + "symfony/process": "^5.4 || ^6.4 || ^7.0", + "symfony/twig-bridge": "^5.4 || ^6.4 || ^7.0", + "symfony/ux-twig-component": "^2.2.0", + "twig/cache-extra": "^3.2" + }, + "bin": [ + "bin/twig-cs-fixer" + ], + "type": "coding-standard", + "autoload": { + "psr-4": { + "TwigCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Vincent Langlet" + } + ], + "description": "A tool to automatically fix Twig code style", + "homepage": "https://github.com/VincentLanglet/Twig-CS-Fixer", + "support": { + "issues": "https://github.com/VincentLanglet/Twig-CS-Fixer/issues", + "source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/3.7.1" + }, + "funding": [ + { + "url": "https://github.com/VincentLanglet", + "type": "github" + } + ], + "time": "2025-05-19T12:24:50+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], @@ -8980,7 +10333,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=8.1", + "php": ">=8.3", "ext-ctype": "*", "ext-iconv": "*" }, diff --git a/config/bundles.php b/config/bundles.php index 48049648..3c7fe0db 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -12,4 +12,7 @@ EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], + Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], ]; diff --git a/config/packages/asset_mapper.yaml b/config/packages/asset_mapper.yaml new file mode 100644 index 00000000..f7653e97 --- /dev/null +++ b/config/packages/asset_mapper.yaml @@ -0,0 +1,11 @@ +framework: + asset_mapper: + # The paths to make available to the asset mapper. + paths: + - assets/ + missing_import_mode: strict + +when@prod: + framework: + asset_mapper: + missing_import_mode: warn diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml index 6899b720..c3eb53dd 100644 --- a/config/packages/cache.yaml +++ b/config/packages/cache.yaml @@ -16,4 +16,4 @@ framework: # Namespaced pools use the above "app" backend by default #pools: - #my.dedicated.cache: null + #my.dedicated.cache: null diff --git a/config/packages/csrf.yaml b/config/packages/csrf.yaml new file mode 100644 index 00000000..40d40405 --- /dev/null +++ b/config/packages/csrf.yaml @@ -0,0 +1,11 @@ +# Enable stateless CSRF protection for forms and logins/logouts +framework: + form: + csrf_protection: + token_id: submit + + csrf_protection: + stateless_token_ids: + - submit + - authenticate + - logout diff --git a/config/packages/debug.yaml b/config/packages/debug.yaml new file mode 100644 index 00000000..ad874afd --- /dev/null +++ b/config/packages/debug.yaml @@ -0,0 +1,5 @@ +when@dev: + debug: + # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. + # See the "server:dump" command to start a new server. + dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index bc682179..120bd6aa 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -1,7 +1,7 @@ doctrine: dbal: - url: '%env(resolve:DATABASE_URL)%' - server_version: '5.7' + url: "%env(resolve:DATABASE_URL)%" + server_version: "5.7" charset: utf8mb4 default_table_options: charset: utf8mb4 @@ -20,26 +20,29 @@ doctrine: mappings: App: is_bundle: false - dir: '%kernel.project_dir%/src/Entity' + dir: "%kernel.project_dir%/src/Entity" prefix: 'App\Entity' alias: App GedmoLoggable: - type: annotation prefix: Gedmo\Loggable\Entity dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity" is_bundle: false + filters: + entity_active: + class: App\Doctrine\EntityActiveFilter + enabled: true when@test: doctrine: dbal: # "TEST_TOKEN" is typically set by ParaTest - dbname_suffix: '_test%env(default::TEST_TOKEN)%' + dbname_suffix: "_test%env(default::TEST_TOKEN)%" when@prod: doctrine: orm: auto_generate_proxy_classes: false - proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' + proxy_dir: "%kernel.build_dir%/doctrine/orm/Proxies" query_cache_driver: type: pool pool: doctrine.system_cache_pool diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml index 83222a8e..73072fff 100644 --- a/config/packages/doctrine_migrations.yaml +++ b/config/packages/doctrine_migrations.yaml @@ -2,7 +2,5 @@ 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' + "DoctrineMigrations": "%kernel.project_dir%/migrations" enable_profiler: false - - diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 6d85c295..414eabf6 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -1,10 +1,13 @@ # see https://symfony.com/doc/current/reference/configuration/framework.html framework: - secret: '%env(APP_SECRET)%' + secret: "%env(APP_SECRET)%" #csrf_protection: true http_method_override: false handle_all_throwables: true + # https://symfony.com/doc/current/deployment/proxies.html + trusted_proxies: "127.0.0.1,REMOTE_ADDR" + # 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: diff --git a/config/packages/knp_paginator.yaml b/config/packages/knp_paginator.yaml new file mode 100644 index 00000000..49d10ebe --- /dev/null +++ b/config/packages/knp_paginator.yaml @@ -0,0 +1,4 @@ +# https://github.com/KnpLabs/KnpPaginatorBundle?tab=readme-ov-file#configuration-example +knp_paginator: + template: + pagination: "@KnpPaginator/Pagination/bootstrap_v5_pagination.html.twig" diff --git a/config/packages/security.yaml b/config/packages/security.yaml index c1b2f6cc..9d0999b8 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,27 +1,24 @@ security: # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: "auto" # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: -# users_in_memory: { memory: null } app_user_provider: entity: class: App\Entity\User - property: email + property: username + firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: form_login: - # "app_login" is the name of the route created previously login_path: app_login check_path: app_login lazy: true -# provider: users_in_memory provider: app_user_provider -# custom_authenticator: App\Security\AppCustomAuthenticator logout: path: admin_logout @@ -34,10 +31,10 @@ security: # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: + - { path: ^/dashboard, roles: ROLE_USER } - { path: ^/admin, roles: ROLE_USER } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - role_hierarchy: ROLE_GROUP_ADMIN: ROLE_USER ROLE_ADMIN: ROLE_GROUP_ADMIN diff --git a/config/packages/stof_doctrine_extensions.yaml b/config/packages/stof_doctrine_extensions.yaml index 13927150..77d7207c 100644 --- a/config/packages/stof_doctrine_extensions.yaml +++ b/config/packages/stof_doctrine_extensions.yaml @@ -6,4 +6,4 @@ stof_doctrine_extensions: default: timestampable: true blameable: true - loggable: true \ No newline at end of file + loggable: true diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml index cbb34825..e298710b 100644 --- a/config/packages/translation.yaml +++ b/config/packages/translation.yaml @@ -1,7 +1,7 @@ framework: default_locale: da translator: - default_path: '%kernel.project_dir%/translations' + default_path: "%kernel.project_dir%/translations" fallbacks: - en providers: diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index f9f4cc53..8aa3d079 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -1,5 +1,9 @@ twig: - default_path: '%kernel.project_dir%/templates' + default_path: "%kernel.project_dir%/templates" + +when@dev: + twig: + debug: true when@test: twig: diff --git a/config/packages/twig_component.yaml b/config/packages/twig_component.yaml new file mode 100644 index 00000000..8af25201 --- /dev/null +++ b/config/packages/twig_component.yaml @@ -0,0 +1,5 @@ +twig_component: + anonymous_template_directory: "components/" + defaults: + # Namespace & directory for components + App\Twig\Components\: "components/" diff --git a/config/routes.yaml b/config/routes.yaml index 2d0cc70c..41ef8140 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -3,5 +3,3 @@ controllers: path: ../src/Controller/ namespace: App\Controller type: attribute - - diff --git a/config/routes/easyadmin.yaml b/config/routes/easyadmin.yaml new file mode 100644 index 00000000..de6be7ec --- /dev/null +++ b/config/routes/easyadmin.yaml @@ -0,0 +1,4 @@ +# https://symfony.com/bundles/EasyAdminBundle/current/dashboards.html#pretty-admin-urls +easyadmin: + resource: . + type: easyadmin.routes diff --git a/config/routes/framework.yaml b/config/routes/framework.yaml index 0fc74bba..d53eff1d 100644 --- a/config/routes/framework.yaml +++ b/config/routes/framework.yaml @@ -1,4 +1,4 @@ when@dev: _errors: - resource: '@FrameworkBundle/Resources/config/routing/errors.xml' + resource: "@FrameworkBundle/Resources/config/routing/errors.xml" prefix: /_error diff --git a/config/routes/web_profiler.yaml b/config/routes/web_profiler.yaml index 8d85319f..1bf88e51 100644 --- a/config/routes/web_profiler.yaml +++ b/config/routes/web_profiler.yaml @@ -1,8 +1,8 @@ when@dev: web_profiler_wdt: - resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' + resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" prefix: /_wdt web_profiler_profiler: - resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' + resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" prefix: /_profiler diff --git a/config/services.yaml b/config/services.yaml index 5327f23a..358224cc 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,21 +8,20 @@ parameters: services: # default configuration for services in *this* file _defaults: - autowire: true # Automatically injects dependencies in your services. + autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name App\: - resource: '../src/' + resource: "../src/" exclude: - - '../src/DependencyInjection/' - - '../src/Entity/' - - '../src/Kernel.php' - + - "../src/DependencyInjection/" + - "../src/Entity/" + - "../src/Kernel.php" # add more service definitions when explicit configuration is needed App\Service\DataExporter: arguments: - $basePath: '%kernel.project_dir%' + $basePath: "%kernel.project_dir%" # please note that last definitions always *replace* previous ones diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 2bd447b1..c75114ee 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,26 +1,27 @@ - +# itk-version: 3.2.3 services: phpfpm: environment: - - PHP_SENDMAIL_PATH='/usr/local/bin/mhsendmail --smtp-addr="mailhog:1025"' + - PHP_SENDMAIL_PATH=/usr/sbin/sendmail -S mail:1025 nginx: labels: - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=ITKBasicAuth@file" - mailhog: - image: itkdev/mailhog + mail: + image: axllent/mailpit + restart: unless-stopped networks: - app - frontend labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.rule=Host(`mailhog.${COMPOSE_SERVER_DOMAIN}`)" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.entrypoints=web" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.middlewares=redirect-to-https" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.rule=Host(`mail.${COMPOSE_SERVER_DOMAIN}`)" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.entrypoints=web" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.middlewares=redirect-to-https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.rule=Host(`mailhog.${COMPOSE_SERVER_DOMAIN}`)" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.entrypoints=websecure" - - "traefik.http.services.mailhog_${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8025" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.middlewares=ITKMailhogAuth@file" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.rule=Host(`mail.${COMPOSE_SERVER_DOMAIN}`)" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.entrypoints=websecure" + - "traefik.http.services.mail_${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8025" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.middlewares=ITKMailhogAuth@file" diff --git a/docker-compose.override.yml b/docker-compose.override.yml index c5612b0a..c772f10a 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,7 +1,23 @@ - services: -###> doctrine/doctrine-bundle ### - database: - ports: - - "5432" -###< doctrine/doctrine-bundle ### + nginx: + labels: + # HTTPS config - uncomment to enable redirect from :80 to :443 + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=redirect-to-https" + - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" + + markdownlint: + image: itkdev/markdownlint + profiles: [dev] + volumes: + - .:/md + + prettier: + # Prettier does not (yet, fcf. + # https://github.com/prettier/prettier/issues/15206) have an official + # docker image. + # https://hub.docker.com/r/jauderho/prettier is good candidate (cf. https://hub.docker.com/search?q=prettier&sort=updated_at&order=desc) + image: jauderho/prettier + profiles: + - dev + volumes: + - ./:/work diff --git a/docker-compose.redirect.yml b/docker-compose.redirect.yml index 88275a40..844b3e6a 100644 --- a/docker-compose.redirect.yml +++ b/docker-compose.redirect.yml @@ -1,4 +1,4 @@ - +# itk-version: 3.2.3 services: nginx: labels: diff --git a/docker-compose.server.yml b/docker-compose.server.yml index d0626969..614d67b1 100644 --- a/docker-compose.server.yml +++ b/docker-compose.server.yml @@ -1,4 +1,4 @@ - +# itk-version: 3.2.3 networks: frontend: external: true @@ -8,7 +8,7 @@ networks: services: phpfpm: - image: itkdev/php8.1-fpm:alpine + image: itkdev/php8.3-fpm:alpine restart: unless-stopped networks: - app @@ -17,7 +17,6 @@ services: environment: - PHP_MAX_EXECUTION_TIME=30 - PHP_MEMORY_LIMIT=128M - - COMPOSER_VERSION=2 volumes: - .:/app @@ -29,12 +28,15 @@ services: - frontend depends_on: - phpfpm - ports: - - '8080' volumes: - - ./.docker/vhost.conf:/etc/nginx/conf.d/default.conf:ro + - ./.docker/templates:/etc/nginx/templates:ro - ./.docker/nginx.conf:/etc/nginx/nginx.conf:ro - - ./:/app:rw + - .:/app + environment: + NGINX_FPM_SERVICE: ${COMPOSE_PROJECT_NAME}-phpfpm-1:9000 + NGINX_WEB_ROOT: /app/public + NGINX_PORT: 8080 + NGINX_MAX_BODY_SIZE: 5M labels: - "traefik.enable=true" - "traefik.docker.network=frontend" diff --git a/docker-compose.yml b/docker-compose.yml index 90f2b5c6..6edca922 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +# itk-version: 3.2.3 networks: frontend: external: true @@ -12,6 +13,12 @@ services: - app ports: - '3306' + healthcheck: + test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ] + start_period: 10s + interval: 10s + timeout: 5s + retries: 3 environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=db @@ -20,19 +27,23 @@ services: #- ENCRYPT=1 # Uncomment to enable database encryption. phpfpm: - image: itkdev/php8.1-fpm:latest + image: itkdev/php8.3-fpm:latest + user: ${COMPOSE_USER:-deploy} networks: - app + extra_hosts: + - "host.docker.internal:host-gateway" environment: - PHP_XDEBUG_MODE=${PHP_XDEBUG_MODE:-off} - PHP_MAX_EXECUTION_TIME=30 - PHP_MEMORY_LIMIT=256M - # - PHP_MAIL=1 # Uncomment to enable mailhog. + # Depending on the setup, you may have to remove --read-envelope-from from msmtp (cf. https://marlam.de/msmtp/msmtp.html) or use SMTP to send mail + - PHP_SENDMAIL_PATH=/usr/bin/msmtp --host=mail --port=1025 --read-recipients --read-envelope-from - DOCKER_HOST_DOMAIN=${COMPOSE_DOMAIN} - - COMPOSER_VERSION=2 - PHP_IDE_CONFIG=serverName=localhost depends_on: - - mariadb + mariadb: + condition: service_healthy volumes: - .:/app @@ -46,8 +57,13 @@ services: ports: - '8080' volumes: - - ./.docker/vhost.conf:/etc/nginx/conf.d/default.conf:ro + - ./.docker/templates:/etc/nginx/templates:ro - .:/app + environment: + NGINX_FPM_SERVICE: ${COMPOSE_PROJECT_NAME}-phpfpm-1:9000 + NGINX_WEB_ROOT: /app/public + NGINX_PORT: 8080 + NGINX_MAX_BODY_SIZE: 5M labels: - "traefik.enable=true" - "traefik.docker.network=frontend" @@ -56,8 +72,8 @@ services: # - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=redirect-to-https" # - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - mailhog: - image: itkdev/mailhog + mail: + image: axllent/mailpit networks: - app - frontend @@ -67,24 +83,5 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - - "traefik.http.routers.${COMPOSE_PROJECT_NAME}Mailhog.rule=Host(`mailhog-${COMPOSE_DOMAIN}`)" - - "traefik.http.services.${COMPOSE_PROJECT_NAME}Mailhog.loadbalancer.server.port=8025" - -###> doctrine/doctrine-bundle ### - database: - image: postgres:${POSTGRES_VERSION:-16}-alpine - environment: - POSTGRES_DB: ${POSTGRES_DB:-app} - # You should definitely change the password in production - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} - POSTGRES_USER: ${POSTGRES_USER:-app} - volumes: - - database_data:/var/lib/postgresql/data:rw - # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! - # - ./docker/db/data:/var/lib/postgresql/data:rw -###< doctrine/doctrine-bundle ### - -volumes: -###> doctrine/doctrine-bundle ### - database_data: -###< doctrine/doctrine-bundle ### + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}mail.rule=Host(`mail-${COMPOSE_DOMAIN}`)" + - "traefik.http.services.${COMPOSE_PROJECT_NAME}mail.loadbalancer.server.port=8025" diff --git a/documentation/Brugsvejledning.md b/documentation/Brugsvejledning.md index d433b198..748d88d9 100644 --- a/documentation/Brugsvejledning.md +++ b/documentation/Brugsvejledning.md @@ -1,21 +1,24 @@ -# ITSTYR - trin for trin opsætning. +# ITSTYR - trin for trin opsætning -## Setup -*Hvis der ikke er data, på 'admin/system' eller 'admin/group', eller oprettet en bruger' skal punkterne i README.md først følges* +## Setup +*Hvis der ikke er data, på 'admin/system' eller 'admin/group', eller oprettet en bruger' skal punkterne i README.md +først følges* ## Generelt + Itstyr er et Smiley-oversigts-site over systemer og anmeldelser. -Websitet skal konfigurers i den rigtige rækkefølge for at få vist smileys. +Websitet skal konfigurers i den rigtige rækkefølge for at få vist smileys. -Først skal der oprettets en Gruppe, og efterfølgende: Kategori, og Tema. +Først skal der oprettets en Gruppe, og efterfølgende: Kategori, og Tema. Til sidst skal man gå ind på dashboarded hvorfra man tilføje status smileys. ## 1. Gruppe + - Klik på Easyadmin Menupunktet Gruppe - - du er nu på gruppes index-side + - du er nu på gruppes index-side - Klik på "tilføj gruppe" - du er nu på gruppes new-side - udfyld textfeltet "Navn" @@ -23,6 +26,7 @@ Til sidst skal man gå ind på dashboarded hvorfra man tilføje status smileys. - klik "Opret" eller "Opret og tilføj ny" ## 2. Kategori + - Klik på Easyadmin Menupunktet Kategorier - du er nu på kategories index-side - Klik på "tilføj kategori" @@ -34,6 +38,7 @@ Til sidst skal man gå ind på dashboarded hvorfra man tilføje status smileys. - klik "Opret" eller "Opret og tilføj ny" ## 3. Tema + - Klik på Easyadmin Menupunktet Tema - du er nu på Temas index-side - Klik på "tilføj Tema" @@ -43,11 +48,11 @@ Til sidst skal man gå ind på dashboarded hvorfra man tilføje status smileys. - klik på ' Anmeldelsr' og tilføj et eller flere Anmeldelser - udfyld "Vægt" med et tal (required) - klik på 'Kategori' og tilføj en kategori - +## 3. Dashboard Systemer + +(Samme fremgangsmåde i Dashboard Anmeldelse) -## 3. Dashboard Systemer -*(Samme fremgangsmåde i Dashboard Anmeldelse)* - Klik på Easyadmin Menupunktet Dashboard Systemer - du er nu på DashboardSystemer index-side - Klik på et system i den skrå bjælke. diff --git a/importmap.php b/importmap.php new file mode 100644 index 00000000..70ebf14f --- /dev/null +++ b/importmap.php @@ -0,0 +1,19 @@ + [ + 'path' => './assets/app.js', + 'entrypoint' => true, + ], +]; diff --git a/migrations/Version20230331103512.php b/migrations/Version20230331103512.php deleted file mode 100644 index 51afd663..00000000 --- a/migrations/Version20230331103512.php +++ /dev/null @@ -1,31 +0,0 @@ -addSql('ALTER TABLE fos_user DROP username_canonical, DROP email_canonical, DROP salt, DROP password, DROP confirmation_token, DROP password_requested_at, CHANGE username username VARCHAR(255) NOT NULL, CHANGE email email VARCHAR(255) NOT NULL, CHANGE roles roles LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\''); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE fos_user ADD username_canonical VARCHAR(180) NOT NULL, ADD email_canonical VARCHAR(180) NOT NULL, ADD salt VARCHAR(255) DEFAULT NULL, ADD password VARCHAR(255) NOT NULL, ADD confirmation_token VARCHAR(180) DEFAULT NULL, ADD password_requested_at DATETIME DEFAULT NULL, CHANGE username username VARCHAR(180) NOT NULL, CHANGE email email VARCHAR(180) NOT NULL, CHANGE roles roles LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\''); - } -} diff --git a/migrations/Version20240903091717.php b/migrations/Version20240903091717.php deleted file mode 100644 index 3c24568d..00000000 --- a/migrations/Version20240903091717.php +++ /dev/null @@ -1,43 +0,0 @@ -addSql('CREATE TABLE test_user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(180) NOT NULL, roles JSON NOT NULL COMMENT \'(DC2Type:json)\', password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME (username), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('ALTER TABLE ext_log_entries CHANGE object_class object_class VARCHAR(191) NOT NULL, CHANGE username username VARCHAR(191) DEFAULT NULL'); - $this->addSql('DROP INDEX UNIQ_4B019DDB5E237E06 ON fos_group'); - $this->addSql('ALTER TABLE fos_group CHANGE name name VARCHAR(255) NOT NULL, CHANGE roles roles JSON NOT NULL COMMENT \'(DC2Type:json)\''); - $this->addSql('ALTER TABLE fos_user ADD password VARCHAR(255) NOT NULL, CHANGE roles roles JSON NOT NULL COMMENT \'(DC2Type:json)\''); - $this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON fos_user (username)'); - $this->addSql('DROP INDEX UNIQ_9775E7085E237E06 ON theme'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DROP TABLE test_user'); - $this->addSql('CREATE UNIQUE INDEX UNIQ_9775E7085E237E06 ON theme (name)'); - $this->addSql('ALTER TABLE fos_group CHANGE name name VARCHAR(180) NOT NULL, CHANGE roles roles LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\''); - $this->addSql('CREATE UNIQUE INDEX UNIQ_4B019DDB5E237E06 ON fos_group (name)'); - $this->addSql('ALTER TABLE ext_log_entries CHANGE object_class object_class VARCHAR(255) NOT NULL, CHANGE username username VARCHAR(255) DEFAULT NULL'); - $this->addSql('DROP INDEX UNIQ_IDENTIFIER_USERNAME ON fos_user'); - $this->addSql('ALTER TABLE fos_user DROP password, CHANGE roles roles JSON NOT NULL COMMENT \'(DC2Type:json)\''); - } -} diff --git a/migrations/Version20250113144422.php b/migrations/Version20250113144422.php new file mode 100644 index 00000000..ef84f628 --- /dev/null +++ b/migrations/Version20250113144422.php @@ -0,0 +1,37 @@ +addSql('CREATE TABLE user_group (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) DEFAULT NULL, roles JSON NOT NULL COMMENT \'(DC2Type:json)\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255) DEFAULT NULL, password VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, enabled TINYINT(1) NOT NULL, last_login DATETIME DEFAULT NULL, roles JSON NOT NULL COMMENT \'(DC2Type:json)\', created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME (username), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE user_user_group (user_id INT NOT NULL, user_group_id INT NOT NULL, INDEX IDX_8F02BF9DA76ED395 (user_id), INDEX IDX_8F02BF9DFE54D947 (user_group_id), PRIMARY KEY(user_id, user_group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE user_user_group ADD CONSTRAINT FK_8F02BF9DA76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE user_user_group ADD CONSTRAINT FK_8F02BF9DFE54D947 FOREIGN KEY (user_group_id) REFERENCES user_group (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE user_user_group DROP FOREIGN KEY FK_8F02BF9DA76ED395'); + $this->addSql('ALTER TABLE user_user_group DROP FOREIGN KEY FK_8F02BF9DFE54D947'); + $this->addSql('DROP TABLE user_group'); + $this->addSql('DROP TABLE user'); + $this->addSql('DROP TABLE user_user_group'); + } +} diff --git a/migrations/Version20250113145607.php b/migrations/Version20250113145607.php new file mode 100644 index 00000000..4d6611cd --- /dev/null +++ b/migrations/Version20250113145607.php @@ -0,0 +1,105 @@ + + */ + private array $groups = []; + + /** + * @var array + */ + private array $users = []; + + /** + * @var array + */ + private array $mapping = []; + + public function getDescription(): string + { + return 'Migrate groups and users to new structure'; + } + + public function preUp(Schema $schema): void + { + $this->groups = $this->getData('SELECT * FROM fos_group'); + foreach ($this->groups as &$group) { + $group['roles'] = unserialize($group['roles']); + } + + $this->users = $this->getData('SELECT * FROM fos_user'); + foreach ($this->users as &$user) { + $user['roles'] = unserialize($user['roles']); + } + + $this->mapping = $this->getData('SELECT * FROM fos_user_user_group'); + } + + public function up(Schema $schema): void + { + // Insert groups. + foreach ($this->groups as $group) { + $this->addSql('INSERT INTO `user_group` (`id`, `name`, `roles`) VALUES ('.$group['id'].", '".$group['name']."', '".json_encode($group['roles'])."')"); + } + + // Insert users. + foreach ($this->users as $user) { + $data = [ + $user['id'], + "'".$user['username']."'", + "'".$user['password']."'", + "'".$user['email']."'", + $user['enabled'], + !empty($user['last_login']) ? "'".$user['last_login']."'" : 'NULL', + "'".json_encode($user['roles'])."'", + "'".$user['created_by']."'", + "'".$user['updated_by']."'", + !empty($user['created_at']) ? "'".$user['created_at']."'" : 'NULL', + !empty($user['updated_at']) ? "'".$user['updated_at']."'" : 'NULL', + ]; + $this->addSql('INSERT INTO `user` (`id`, `username`, `password`, `email`, `enabled`, `last_login`, `roles`, `created_by`, `updated_by`, `created_at`, `updated_at`) VALUES ('.implode(',', $data).')'); + } + + // Link users and groups. + foreach ($this->mapping as $mapping) { + $this->addSql('INSERT INTO `user_user_group` (`user_id`, `user_group_id`) VALUES ('.$mapping['user_id'].', '.$mapping['group_id'].')'); + } + } + + public function down(Schema $schema): void + { + // There is no down for this migration. So left empty. + } + + /** + * Helper function to get data from the database. + * + * @param string $sql + * SQL statement to fetch data + * + * @return array + * The data fetched from the database as associative array + * + * @throws Exception + * Database error + */ + private function getData(string $sql): array + { + $stmt = $this->connection->executeQuery($sql); + + return $stmt->fetchAllAssociative(); + } +} diff --git a/migrations/Version20250114085724.php b/migrations/Version20250114085724.php new file mode 100644 index 00000000..beeec39c --- /dev/null +++ b/migrations/Version20250114085724.php @@ -0,0 +1,48 @@ +addSql('ALTER TABLE system_group DROP FOREIGN KEY FK_390FDF5FFE54D947'); + $this->addSql('ALTER TABLE report_group DROP FOREIGN KEY FK_47DC43BCFE54D947'); + $this->addSql('ALTER TABLE group_report_themes DROP FOREIGN KEY FK_63582903FE54D947'); + $this->addSql('ALTER TABLE group_system_themes DROP FOREIGN KEY FK_5A25495DFE54D947'); + + // Drop internal FOS user -> groups mapping keys. + $this->addSql('ALTER TABLE fos_user_user_group DROP FOREIGN KEY FK_B3C77447FE54D947'); + $this->addSql('ALTER TABLE fos_user_user_group DROP FOREIGN KEY FK_B3C77447A76ED395'); + + // Remove tables, data was migrated in last migration step. + $this->addSql('DROP TABLE fos_group'); + $this->addSql('DROP TABLE fos_user_user_group'); + $this->addSql('DROP TABLE fos_user'); + + // Add new foreign keys mapping the new user/group tables + $this->addSql('ALTER TABLE group_system_themes ADD CONSTRAINT FK_5A25495DFE54D947 FOREIGN KEY (group_id) REFERENCES `user_group` (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE group_report_themes ADD CONSTRAINT FK_63582903FE54D947 FOREIGN KEY (group_id) REFERENCES `user_group` (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE report_group ADD CONSTRAINT FK_47DC43BCFE54D947 FOREIGN KEY (group_id) REFERENCES `user_group` (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE system_group ADD CONSTRAINT FK_390FDF5FFE54D947 FOREIGN KEY (group_id) REFERENCES `user_group` (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // There is no down for this migration. So left empty. + } +} diff --git a/migrations/Version20250114090744.php b/migrations/Version20250114090744.php new file mode 100644 index 00000000..e7a121f7 --- /dev/null +++ b/migrations/Version20250114090744.php @@ -0,0 +1,49 @@ +addSql('ALTER TABLE category CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE ext_log_entries CHANGE object_class object_class VARCHAR(191) NOT NULL, CHANGE username username VARCHAR(191) DEFAULT NULL'); + $this->addSql('ALTER TABLE import_run CHANGE datetime datetime DATETIME DEFAULT NULL, CHANGE result result TINYINT(1) DEFAULT NULL, CHANGE type type VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE question CHANGE question question LONGTEXT DEFAULT NULL, CHANGE sort_order sort_order INT DEFAULT NULL'); + $this->addSql('ALTER TABLE report CHANGE name name VARCHAR(255) DEFAULT NULL, CHANGE sys_link sys_link VARCHAR(255) DEFAULT NULL, CHANGE sys_system_owner sys_system_owner VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE self_service_available_from_item CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE system CHANGE name name VARCHAR(255) DEFAULT NULL, CHANGE sys_link sys_link VARCHAR(255) DEFAULT NULL, CHANGE sys_system_owner sys_system_owner VARCHAR(255) DEFAULT NULL'); + $this->addSql('DROP INDEX UNIQ_9775E7085E237E06 ON theme'); + $this->addSql('ALTER TABLE theme CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE theme_category CHANGE sort_order sort_order INT DEFAULT 0'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE ext_log_entries CHANGE object_class object_class VARCHAR(255) NOT NULL, CHANGE username username VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE question CHANGE question question LONGTEXT NOT NULL, CHANGE sort_order sort_order INT NOT NULL'); + $this->addSql('ALTER TABLE category CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE self_service_available_from_item CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE theme_category CHANGE sort_order sort_order INT DEFAULT 0 NOT NULL'); + $this->addSql('ALTER TABLE system CHANGE name name VARCHAR(255) NOT NULL, CHANGE sys_system_owner sys_system_owner VARCHAR(255) NOT NULL, CHANGE sys_link sys_link VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE report CHANGE name name VARCHAR(255) NOT NULL, CHANGE sys_system_owner sys_system_owner VARCHAR(255) NOT NULL, CHANGE sys_link sys_link VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE theme CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_9775E7085E237E06 ON theme (name)'); + $this->addSql('ALTER TABLE import_run CHANGE datetime datetime DATETIME NOT NULL, CHANGE result result TINYINT(1) NOT NULL, CHANGE type type VARCHAR(255) NOT NULL'); + } +} diff --git a/migrations/Version20250114101024.php b/migrations/Version20250114101024.php new file mode 100644 index 00000000..1d600b91 --- /dev/null +++ b/migrations/Version20250114101024.php @@ -0,0 +1,107 @@ + + */ + private array $report_groups = []; + + /** + * @var array + */ + private array $system_groups = []; + + public function getDescription(): string + { + return 'Migrate relationship to user groups'; + } + + public function preUp(Schema $schema): void + { + $this->report_groups = $this->getData('SELECT * FROM report_group'); + $this->system_groups = $this->getData('SELECT * FROM system_group'); + } + + public function up(Schema $schema): void + { + // Create new join tables. + $this->addSql('CREATE TABLE report_user_group (report_id INT NOT NULL, user_group_id INT NOT NULL, INDEX IDX_9C4093A64BD2A4C0 (report_id), INDEX IDX_9C4093A61ED93D47 (user_group_id), PRIMARY KEY(report_id, user_group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE system_user_group (system_id INT NOT NULL, user_group_id INT NOT NULL, INDEX IDX_3AD1AFA4D0952FA5 (system_id), INDEX IDX_3AD1AFA41ED93D47 (user_group_id), PRIMARY KEY(system_id, user_group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + + // Add new foreign keys mapping report and system with the new user_group table + $this->addSql('ALTER TABLE report_user_group ADD CONSTRAINT FK_9C4093A64BD2A4C0 FOREIGN KEY (report_id) REFERENCES report (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE report_user_group ADD CONSTRAINT FK_9C4093A61ED93D47 FOREIGN KEY (user_group_id) REFERENCES user_group (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE system_user_group ADD CONSTRAINT FK_3AD1AFA4D0952FA5 FOREIGN KEY (system_id) REFERENCES system (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE system_user_group ADD CONSTRAINT FK_3AD1AFA41ED93D47 FOREIGN KEY (user_group_id) REFERENCES user_group (id) ON DELETE CASCADE'); + + // Migrate data. + foreach ($this->report_groups as $mapping) { + $this->addSql('INSERT INTO `report_user_group` (`report_id`, `user_group_id`) VALUES ('.$mapping['report_id'].', '.$mapping['group_id'].')'); + } + foreach ($this->system_groups as $mapping) { + $this->addSql('INSERT INTO `system_user_group` (`system_id`, `user_group_id`) VALUES ('.$mapping['system_id'].', '.$mapping['group_id'].')'); + } + + // Remove old tables. + $this->addSql('ALTER TABLE system_group DROP FOREIGN KEY FK_390FDF5FFE54D947'); + $this->addSql('ALTER TABLE system_group DROP FOREIGN KEY FK_390FDF5FD0952FA5'); + $this->addSql('ALTER TABLE report_group DROP FOREIGN KEY FK_47DC43BCFE54D947'); + $this->addSql('ALTER TABLE report_group DROP FOREIGN KEY FK_47DC43BC4BD2A4C0'); + $this->addSql('DROP TABLE system_group'); + $this->addSql('DROP TABLE report_group'); + + // Update the mapping tabelles 'group_system_themes' and 'group_report_themes' + $this->addSql('ALTER TABLE user_user_group RENAME INDEX idx_8f02bf9da76ed395 TO IDX_28657971A76ED395'); + $this->addSql('ALTER TABLE user_user_group RENAME INDEX idx_8f02bf9dfe54d947 TO IDX_286579711ED93D47'); + $this->addSql('ALTER TABLE group_system_themes DROP FOREIGN KEY FK_5A25495DFE54D947'); + $this->addSql('DROP INDEX IDX_5A25495DFE54D947 ON group_system_themes'); + $this->addSql('DROP INDEX `primary` ON group_system_themes'); + $this->addSql('ALTER TABLE group_system_themes CHANGE group_id user_group_id INT NOT NULL'); + $this->addSql('ALTER TABLE group_system_themes ADD CONSTRAINT FK_5A25495D1ED93D47 FOREIGN KEY (user_group_id) REFERENCES user_group (id) ON DELETE CASCADE'); + $this->addSql('CREATE INDEX IDX_5A25495D1ED93D47 ON group_system_themes (user_group_id)'); + $this->addSql('ALTER TABLE group_system_themes ADD PRIMARY KEY (user_group_id, theme_id)'); + $this->addSql('ALTER TABLE group_report_themes DROP FOREIGN KEY FK_63582903FE54D947'); + $this->addSql('DROP INDEX IDX_63582903FE54D947 ON group_report_themes'); + $this->addSql('DROP INDEX `primary` ON group_report_themes'); + $this->addSql('ALTER TABLE group_report_themes CHANGE group_id user_group_id INT NOT NULL'); + $this->addSql('ALTER TABLE group_report_themes ADD CONSTRAINT FK_635829031ED93D47 FOREIGN KEY (user_group_id) REFERENCES user_group (id) ON DELETE CASCADE'); + $this->addSql('CREATE INDEX IDX_635829031ED93D47 ON group_report_themes (user_group_id)'); + $this->addSql('ALTER TABLE group_report_themes ADD PRIMARY KEY (user_group_id, theme_id)'); + } + + public function down(Schema $schema): void + { + // There is no down for this migration. So left empty. + } + + /** + * Helper function to get data from the database. + * + * @param string $sql + * SQL statement to fetch data + * + * @return array + * The data fetched from the database as associative array + * + * @throws Exception + * Database error + */ + private function getData(string $sql): array + { + $stmt = $this->connection->executeQuery($sql); + + return $stmt->fetchAllAssociative(); + } +} diff --git a/migrations/Version20250325201356.php b/migrations/Version20250325201356.php new file mode 100644 index 00000000..29a166c3 --- /dev/null +++ b/migrations/Version20250325201356.php @@ -0,0 +1,31 @@ +addSql('CREATE UNIQUE INDEX UNIQ_8D93D649E7927C74 ON user (email)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP INDEX UNIQ_8D93D649E7927C74 ON user'); + } +} diff --git a/migrations/Version20250519132433.php b/migrations/Version20250519132433.php new file mode 100644 index 00000000..a269c1de --- /dev/null +++ b/migrations/Version20250519132433.php @@ -0,0 +1,35 @@ +addSql(<<<'SQL' + ALTER TABLE theme_category CHANGE theme_id theme_id INT DEFAULT NULL + SQL); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql(<<<'SQL' + ALTER TABLE theme_category CHANGE theme_id theme_id INT NOT NULL + SQL); + } +} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000..7d82f710 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,41 @@ +parameters: + ignoreErrors: + - message: '#^Call to function is_null\(\) with Doctrine\\Common\\Collections\\Collection\ will always evaluate to false\.$#' + identifier: function.impossibleType + count: 2 + path: src/Command/AssignGroupsCommand.php + + - message: '#^Access to an undefined property App\\Controller\\Admin\\CustomDashboardCrudController\:\:\$entity\.$#' + identifier: property.notFound + count: 1 + path: src/Controller/Admin/CustomDashboardCrudController.php + + - message: '#^Call to an undefined static method App\\Controller\\Admin\\AbstractSystatusDashboardController\:\:showAction\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Controller/Admin/CustomDashboardCrudController.php + + - message: '#^Unable to resolve the template type T in call to method Doctrine\\ORM\\EntityManagerInterface\:\:getRepository\(\)$#' + identifier: argument.templateType + count: 3 + path: src/Controller/Admin/CustomDashboardCrudController.php + + - message: '#^Unable to resolve the template type T in call to method Doctrine\\ORM\\EntityManagerInterface\:\:getRepository\(\)$#' + identifier: argument.templateType + count: 1 + path: src/Controller/Admin/EntityFilterTrait.php + + - message: '#^Call to an undefined method Traversable\\:\:uasort\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Entity/Theme.php + + - message: '#^Negated boolean expression is always true\.$#' + identifier: booleanNot.alwaysTrue + count: 1 + path: src/Service/DataExporter.php + + - message: '#^Call to function method_exists\(\) with ''Symfony\\\\Component\\\\Dotenv\\\\Dotenv'' and ''bootEnv'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: tests/bootstrap.php diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 00000000..f14bf573 --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,11 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 6 + paths: + - bin/ + - config/ + - public/ + - src/ + - tests/ diff --git a/public/form_category.js b/public/form_category.js index 3ba29d0e..d872300a 100644 --- a/public/form_category.js +++ b/public/form_category.js @@ -1,23 +1,20 @@ -// See https://symfony.com/doc/current/form/form_collections.html -var $collectionHolder; +const addQuestionButton = $(''); +const wrapper = $('').append(addQuestionButton); +const newLinkLi = $('').append(wrapper); -var $addQuestionButton = $(''); -var wrapper = $('').append($addQuestionButton); -var $newLinkLi = $('').append(wrapper); - -function addQuestionForm ($collectionHolder, $newLinkLi) { - var prototype = $collectionHolder.data('prototype'); - var index = $collectionHolder.data('index'); - var newForm = prototype; +function addQuestionForm (collectionHolder, $newLinkLi) { + const prototype = collectionHolder.data('prototype'); + const index = collectionHolder.data('index'); + let newForm = prototype; newForm = newForm.replace(/__name__/g, index); - $collectionHolder.data('index', index + 1); + collectionHolder.data('index', index + 1); $newLinkLi.before(newForm); addQuestionFormDeleteLink($newLinkLi.prev()); } function addQuestionFormDeleteLink ($questionForm) { - var $removeFormButton = $(''); + const $removeFormButton = $(''); $questionForm.append($removeFormButton); @@ -27,17 +24,17 @@ function addQuestionFormDeleteLink ($questionForm) { } jQuery(document).ready(function () { - $collectionHolder = $('tbody.questions'); + collectionHolder = $('tbody.questions'); - $collectionHolder.find('tr').each(function () { + collectionHolder.find('tr').each(function () { addQuestionFormDeleteLink($(this)); }); - $collectionHolder.append($newLinkLi); + collectionHolder.append(newLinkLi); - $collectionHolder.data('index', $collectionHolder.find(':input').length); + collectionHolder.data('index', collectionHolder.find(':input').length); - $addQuestionButton.on('click', function (e) { - addQuestionForm($collectionHolder, $newLinkLi); + addQuestionButton.on('click', function (e) { + addQuestionForm(collectionHolder, newLinkLi); }); }); diff --git a/public/form_theme.js b/public/form_theme.js index d9efba5e..2bac396d 100644 --- a/public/form_theme.js +++ b/public/form_theme.js @@ -1,23 +1,19 @@ -// See https://symfony.com/doc/current/form/form_collections.html - -var $collectionHolder; - -var $addThemeCategoryButton = $(''); -var wrapper = $('').append($addThemeCategoryButton); -var $newLinkLi = $('').append(wrapper); - -function addThemeCategoryForm ($collectionHolder, $newLinkLi) { - var prototype = $collectionHolder.data('prototype'); - var index = $collectionHolder.data('index'); - var newForm = prototype; +const addThemeCategoryButton = $(''); +const wrapper = $('').append(addThemeCategoryButton); +const newLinkLi = $('').append(wrapper); + +function addThemeCategoryForm (collectionHolder, $newLinkLi) { + const prototype = collectionHolder.data('prototype'); + const index = collectionHolder.data('index'); + let newForm = prototype; newForm = newForm.replace(/__name__/g, index); - $collectionHolder.data('index', index + 1); + collectionHolder.data('index', index + 1); $newLinkLi.before(newForm); addThemeCategoryFormDeleteLink($newLinkLi.prev()); } function addThemeCategoryFormDeleteLink ($themeCategoryForm) { - var $removeFormButton = $(''); + const $removeFormButton = $(''); $themeCategoryForm.append($removeFormButton); @@ -27,17 +23,17 @@ function addThemeCategoryFormDeleteLink ($themeCategoryForm) { } jQuery(document).ready(function () { - $collectionHolder = $('tbody.themeCategories'); + collectionHolder = $('tbody.themeCategories'); - $collectionHolder.find('tr').each(function () { + collectionHolder.find('tr').each(function () { addThemeCategoryFormDeleteLink($(this)); }); - $collectionHolder.append($newLinkLi); + collectionHolder.append(newLinkLi); - $collectionHolder.data('index', $collectionHolder.find(':input').length); + collectionHolder.data('index', collectionHolder.find(':input').length); - $addThemeCategoryButton.on('click', function (e) { - addThemeCategoryForm($collectionHolder, $newLinkLi); + addThemeCategoryButton.on('click', function (e) { + addThemeCategoryForm(collectionHolder, newLinkLi); }); }); diff --git a/public/index.php b/public/index.php index 721caf63..b6ec432a 100644 --- a/public/index.php +++ b/public/index.php @@ -1,40 +1,7 @@ load(__DIR__.'/../.env'); -} - -$env = $_SERVER['APP_ENV'] ?? 'dev'; -$debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)); - -if ($debug) { - umask(0000); - - Debug::enable(); -} - -if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { - Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); -} - -if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { - Request::setTrustedHosts(explode(',', $trustedHosts)); -} - -$kernel = new Kernel($env, $debug); -$request = Request::createFromGlobals(); -$response = $kernel->handle($request); -$response->send(); -$kernel->terminate($request, $response); +return fn (array $context) => new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..c325b1ee --- /dev/null +++ b/rector.php @@ -0,0 +1,26 @@ +withPaths([ + __DIR__.'/assets', + __DIR__.'/config', + __DIR__.'/public', + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->withPhpSets(php83: true) + ->withAttributesSets(symfony: true, doctrine: true, gedmo: true) + ->withSymfonyContainerXml(__DIR__.'/var/cache/dev/App_KernelDevDebugContainer.xml') + ->withSets([ + SymfonySetList::SYMFONY_64, + SymfonySetList::SYMFONY_CODE_QUALITY, + SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, + ]) + ->withTypeCoverageLevel(0) + ->withDeadCodeLevel(0) + ->withCodeQualityLevel(0); diff --git a/src/Command/AbstractImportCommand.php b/src/Command/AbstractImportCommand.php index b3d88d67..a88feb27 100644 --- a/src/Command/AbstractImportCommand.php +++ b/src/Command/AbstractImportCommand.php @@ -10,15 +10,11 @@ abstract class AbstractImportCommand extends Command { - protected EntityManagerInterface $entityManager; - protected BaseImporter $importer; - - public function __construct(BaseImporter $importer, EntityManagerInterface $entityManager) + public function __construct( + protected BaseImporter $importer, + protected EntityManagerInterface $entityManager) { parent::__construct(); - - $this->entityManager = $entityManager; - $this->importer = $importer; } /** @@ -26,7 +22,7 @@ public function __construct(BaseImporter $importer, EntityManagerInterface $enti * * @throws \Exception */ - protected function import(string $type, string $src, OutputInterface $output) + protected function import(string $type, string $src, OutputInterface $output): void { $success = true; $errorMessage = null; @@ -45,16 +41,16 @@ protected function import(string $type, string $src, OutputInterface $output) /** * Record import run. * - * @param string $type - * The type of the import - * @param bool $success - * Success of run + * @param string $type + * The type of the import + * @param bool $success + * Success of run * @param string|null $output - * Output message or null + * Output message or null * * @throws \Exception */ - protected function recordImportRun(string $type, bool $success, ?string $output = null) + protected function recordImportRun(string $type, bool $success, ?string $output = null): void { $importRun = new ImportRun(); $importRun->setDatetime(new \DateTime()); diff --git a/src/Command/AssignGroupsCommand.php b/src/Command/AssignGroupsCommand.php index 41f9842c..7cd3f888 100644 --- a/src/Command/AssignGroupsCommand.php +++ b/src/Command/AssignGroupsCommand.php @@ -2,6 +2,7 @@ namespace App\Command; +use App\Entity\Report; use App\Repository\GroupRepository; use App\Repository\ReportRepository; use App\Repository\SystemRepository; @@ -12,25 +13,16 @@ class AssignGroupsCommand extends Command { - private $reportRepository; - private $systemRepository; - private $groupRepository; - private $entityManager; - public function __construct( - ReportRepository $reportRepository, - SystemRepository $systemRepository, - GroupRepository $groupRepository, - EntityManagerInterface $entityManager, + private readonly ReportRepository $reportRepository, + private readonly SystemRepository $systemRepository, + private readonly GroupRepository $groupRepository, + private readonly EntityManagerInterface $entityManager, ) { parent::__construct(); - $this->reportRepository = $reportRepository; - $this->systemRepository = $systemRepository; - $this->groupRepository = $groupRepository; - $this->entityManager = $entityManager; } - protected function configure() + protected function configure(): void { $this ->setName('itstyr:group:assign') @@ -40,11 +32,12 @@ protected function configure() ; } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $reports = $this->reportRepository->findAll(); $systems = $this->systemRepository->findAll(); + /** @var Report $report */ foreach ($reports as $report) { if (!is_null($report->getSysOwner())) { $e = $report->getSysOwner(); @@ -59,8 +52,8 @@ protected function execute(InputInterface $input, OutputInterface $output) ); if ($findGroup) { - if (is_null($report->getGroup())) { - $report->setGroup($findGroup); + if (is_null($report->getGroups())) { + $report->addGroup($findGroup); } if (is_null($report->getSysOwnerSub())) { @@ -92,8 +85,8 @@ protected function execute(InputInterface $input, OutputInterface $output) ); if ($findGroup) { - if (is_null($system->getGroup())) { - $system->setGroup($findGroup); + if (is_null($system->getGroups())) { + $system->addGroup($findGroup); } if (is_null($system->getSysOwnerSub())) { @@ -112,5 +105,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $this->entityManager->flush(); + + return Command::SUCCESS; } } diff --git a/src/Command/CreateUserCommand.php b/src/Command/CreateUserCommand.php new file mode 100644 index 00000000..5a75877d --- /dev/null +++ b/src/Command/CreateUserCommand.php @@ -0,0 +1,92 @@ +addArgument('username', InputArgument::REQUIRED, 'The username of the user') + ->addArgument('email', InputArgument::REQUIRED, 'The email of the user') + ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password of the user, if not set, a random password will be generated') + ->addOption('super', null, InputOption::VALUE_NONE, 'Add "super admin" user role to the user') + ->addOption('group-id', null, InputOption::VALUE_REQUIRED, 'The ID of the group to add the user to') + ->addOption('roles', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Roles to add to the user', ['ROLE_ADMIN']) + ; + } + + /** + * @throws RandomException + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $username = $input->getArgument('username'); + $email = $input->getArgument('email'); + + $password = $input->getOption('password'); + $groupId = $input->getOption('group-id'); + $roles = $input->getOption('roles'); + + $super = $input->getOption('super'); + if ($super) { + $roles[] = 'ROLE_SUPER_ADMIN'; + } + + if (!$password) { + $password = bin2hex(random_bytes(5)); + $io->note('Password: '.$password); + } + + $user = new User(); + + if ($groupId) { + $group = $this->groupRepository->find($groupId); + if (is_null($group)) { + $io->error('Group not found'); + + return Command::FAILURE; + } + $user->addGroup($group); + } + + $user->setUsername($username); + $user->setEmail($email); + $user->setPassword($this->passwordHasher->hashPassword($user, $password)); + $user->setRoles(array_unique($roles)); + $user->setEnabled(true); + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $io->success('User have been created.'); + + return Command::SUCCESS; + } +} diff --git a/src/Command/ReportImportCommand.php b/src/Command/ReportImportCommand.php index 0f63c045..41e19446 100644 --- a/src/Command/ReportImportCommand.php +++ b/src/Command/ReportImportCommand.php @@ -16,7 +16,7 @@ public function __construct(ReportImporter $reportImporter, EntityManagerInterfa parent::__construct($reportImporter, $entityManager); } - protected function configure() + protected function configure(): void { $this ->setName('itstyr:import:report') @@ -25,7 +25,10 @@ protected function configure() ; } - protected function execute(InputInterface $input, OutputInterface $output) + /** + * @throws \Exception + */ + protected function execute(InputInterface $input, OutputInterface $output): int { $this->import(Report::class, $input->getArgument('src'), $output); diff --git a/src/Command/SuperUserCommand.php b/src/Command/SuperUserCommand.php deleted file mode 100644 index dd2d64c9..00000000 --- a/src/Command/SuperUserCommand.php +++ /dev/null @@ -1,56 +0,0 @@ -passwordHasher = $passwordHasher; - $this->entitManager = $entityManager; - parent::__construct(); - } - - protected function configure(): void - { - $this - ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') - ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $user = new User(); - $user->setUsername('a'); - $user->setEmail('a@a.com'); - $user->setPassword($this->passwordHasher->hashPassword($user, 'a')); - $user->setRoles(['ROLE_SUPER_ADMIN']); - $user->setEnabled(true); - $this->entitManager->persist($user); - $this->entitManager->flush(); - - $io->success('you have created email:: a@a , with password:: a'); - - return Command::SUCCESS; - } -} diff --git a/src/Command/SystemImportCommand.php b/src/Command/SystemImportCommand.php index f70cf8b7..13ec6ef8 100644 --- a/src/Command/SystemImportCommand.php +++ b/src/Command/SystemImportCommand.php @@ -16,7 +16,7 @@ public function __construct(SystemImporter $systemImporter, EntityManagerInterfa parent::__construct($systemImporter, $entityManager); } - protected function configure() + protected function configure(): void { $this ->setName('itstyr:import:system') diff --git a/src/Command/UpdateUserCommand.php b/src/Command/UpdateUserCommand.php new file mode 100644 index 00000000..14e13134 --- /dev/null +++ b/src/Command/UpdateUserCommand.php @@ -0,0 +1,122 @@ +addArgument('username', InputArgument::REQUIRED, 'The username of the user to update') + ->addArgument('email', InputArgument::OPTIONAL, 'The email of the user') + ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password of the user, if not set, a random password will be generated') + ->addOption('generate-password', null, InputOption::VALUE_NONE, 'Generate a random password for the user') + ->addOption('super', null, InputOption::VALUE_NONE, 'Add "super admin" user role to the user') + ->addOption('group-id', null, InputOption::VALUE_REQUIRED, 'The ID of the group to add the user to') + ->addOption('roles', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Roles to add to the user') + ->addOption('enable', null, InputOption::VALUE_NONE, 'Enable the user') + ->addOption('disable', null, InputOption::VALUE_NONE, 'Disable the user') + ; + } + + /** + * @throws RandomException + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $username = $input->getArgument('username'); + $email = $input->getArgument('email'); + $password = $input->getOption('password'); + $generatePassword = $input->getOption('generate-password'); + + $groupId = $input->getOption('group-id'); + $roles = $input->getOption('roles'); + + $enable = $input->getOption('enable'); + $disable = $input->getOption('disable'); + + $super = $input->getOption('super'); + if ($super) { + $roles[] = 'ROLE_SUPER_ADMIN'; + } + + if ($generatePassword) { + if (null !== $password) { + $io->info('Random password will be generated. As you can not use supplied password with --generate-password in same command'); + } + $password = bin2hex(random_bytes(5)); + $io->note('Password: '.$password); + } + + $user = $this->userRepository->findOneBy(['username' => $username]); + if (is_null($user)) { + $io->error('User not found'); + + return Command::FAILURE; + } + + if ($email) { + $user->setEmail($email); + } + + if ($password || $generatePassword) { + $user->setPassword($this->passwordHasher->hashPassword($user, $password)); + } + + if ($disable) { + $user->setEnabled(false); + } + if ($enable) { + $user->setEnabled(true); + } + + if (!empty($roles)) { + $user->setRoles(array_unique($roles)); + } + + if ($groupId) { + $group = $this->groupRepository->find($groupId); + if (is_null($group)) { + $io->error('Group not found'); + + return Command::FAILURE; + } + $user->addGroup($group); + } + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $io->success('User have been updated.'); + + return Command::SUCCESS; + } +} diff --git a/src/Command/UserCreateCommand.php b/src/Command/UserCreateCommand.php new file mode 100644 index 00000000..0adb56e9 --- /dev/null +++ b/src/Command/UserCreateCommand.php @@ -0,0 +1,72 @@ +addArgument('email', InputArgument::REQUIRED, 'The email') + ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password') + ->addOption('role', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The roles') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $email = $input->getArgument('email'); + while (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + throw new InvalidArgumentException(sprintf('Invalid email: %s', $email)); + } + + $user = $this->userRepository->findOneBy(['email' => $email]); + if ($user) { + throw new InvalidArgumentException(sprintf('User with email %s already exists', $email)); + } + + $roles = array_unique([ + ...(array) $input->getOption('role'), + 'ROLE_USER', + ]); + + $password = $input->getOption('password') ?? ByteString::fromRandom(12); + + $user = new User(); + $user->setUsername($email); + $user->setEmail($email); + $user->setPassword($this->passwordHasher->hashPassword($user, $password)); + $user->setRoles($roles); + $user->setEnabled(true); + $this->userRepository->save($user, true); + + $io->success(sprintf('User %s (%s) created with password %s and roles %s', $user->getUsername(), $user->getEmail(), $password, implode(', ', $user->getRoles()))); + + return Command::SUCCESS; + } +} diff --git a/src/Command/UserPasswordCommand.php b/src/Command/UserPasswordCommand.php new file mode 100644 index 00000000..e75dd234 --- /dev/null +++ b/src/Command/UserPasswordCommand.php @@ -0,0 +1,55 @@ +addArgument('email', InputArgument::REQUIRED, 'The email') + ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $email = $input->getArgument('email'); + $user = $this->userRepository->findOneBy(['email' => $email]); + if (!$user) { + throw new InvalidArgumentException(sprintf('User not found: %s', $email)); + } + + $password = $input->getOption('password') ?? ByteString::fromRandom(12); + $user->setPassword($this->passwordHasher->hashPassword($user, $password)); + $this->userRepository->save($user, true); + + $io->success(sprintf('Password for user %s (%s) set to %s', $user->getUsername(), $user->getEmail(), $password)); + + return Command::SUCCESS; + } +} diff --git a/src/Command/UserRolesCommand.php b/src/Command/UserRolesCommand.php new file mode 100644 index 00000000..fbb8534a --- /dev/null +++ b/src/Command/UserRolesCommand.php @@ -0,0 +1,55 @@ +addArgument('email', InputArgument::REQUIRED, 'The email') + ->addOption('add', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The roles to add') + ->addOption('remove', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The roles to remove') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $email = $input->getArgument('email'); + $user = $this->userRepository->findOneBy(['email' => $email]); + if (!$user) { + throw new InvalidArgumentException(sprintf('User not found: %s', $email)); + } + + $roles = $user->getRoles(); + $roles = array_merge($roles, (array) $input->getOption('add')); + $roles = array_diff($roles, (array) $input->getOption('remove')); + $user->setRoles(array_unique($roles)); + $this->userRepository->save($user, true); + + $io->success(sprintf('User %s (%s) now has the roles %s', $user->getUsername(), $user->getEmail(), implode(', ', $user->getRoles()))); + + return Command::SUCCESS; + } +} diff --git a/src/Controller/Admin/AbstractFilterableCrudController.php b/src/Controller/Admin/AbstractFilterableCrudController.php new file mode 100644 index 00000000..d0508bf4 --- /dev/null +++ b/src/Controller/Admin/AbstractFilterableCrudController.php @@ -0,0 +1,69 @@ +setSearchFields(null) + ->overrideTemplate('crud/index', 'admin/crud/index.html.twig'); + } + + #[\Override] + public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore + { + $responseParameters = parent::configureResponseParameters($responseParameters); + if ($pageName = $responseParameters->get('pageName')) { + if (Crud::PAGE_INDEX === $pageName) { + // Add our custom filters on the index page. + $filterFormBuilder = $this->createFilterFormBuilder(); + $this->buildCustomFilters( + $this->getContext()->getRequest(), + $this->getContext()->getEntity()->getFqcn(), + $filterFormBuilder + ); + $responseParameters->set('custom_filters', $filterFormBuilder->getForm()->createView()); + } + } + + return $responseParameters; + } + + #[\Override] + public function createIndexQueryBuilder( + SearchDto $searchDto, + EntityDto $entityDto, + FieldCollection $fields, + FilterCollection $filters, + ): QueryBuilder { + $builder = parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters); + $filterParameters = $this->getFilterParameters($searchDto->getRequest()); + + $this->applyFilters($builder, $filterParameters, $entityDto->getFqcn()); + + return $builder; + } +} diff --git a/src/Controller/Admin/AbstractSystatusDashboardController.php b/src/Controller/Admin/AbstractSystatusDashboardController.php index c0bf138c..afa47f8f 100644 --- a/src/Controller/Admin/AbstractSystatusDashboardController.php +++ b/src/Controller/Admin/AbstractSystatusDashboardController.php @@ -3,12 +3,12 @@ namespace App\Controller\Admin; use App\Entity\Category; -use App\Entity\Group; use App\Entity\ImportRun; use App\Entity\Report; use App\Entity\System; use App\Entity\Theme; use App\Entity\User; +use App\Entity\UserGroup; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard; use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem; @@ -16,6 +16,7 @@ abstract class AbstractSystatusDashboardController extends AbstractDashboardController { + #[\Override] public function configureDashboard(): Dashboard { return Dashboard::new() @@ -24,36 +25,36 @@ public function configureDashboard(): Dashboard ; } + #[\Override] public function configureCrud(): Crud { return Crud::new() ->overrideTemplate('label/null', 'easy_admin_overrides/label_null.html.twig') + ->showEntityActionsInlined() ; } + #[\Override] public function configureMenuItems(): iterable { return [ - MenuItem::section('Dashboard '), - MenuItem::linkToRoute('menu.dashboard.reports', 'fas fa-file-alt', 'dashboard', ['entityType' => 'report']), - MenuItem::linkToRoute('menu.dashboard.systems', 'fas fa-cogs', 'dashboard', ['entityType' => 'system']), + MenuItem::section('menu.dashboards'), + MenuItem::linkToUrl('menu.dashboard.reports', 'fas fa-file-alt', $this->generateUrl('dashboard', ['entityType' => 'report'])), + MenuItem::linkToUrl('menu.dashboard.systems', 'fas fa-cogs', $this->generateUrl('dashboard', ['entityType' => 'system'])), - MenuItem::section('Sysstatus'), + MenuItem::section('menu.sysstatus'), MenuItem::linkToCrud('menu.list.reports', 'fas fa-list', Report::class), MenuItem::linkToCrud('menu.list.systems', 'fas fa-cog', System::class), - MenuItem::section('Konfiguration'), + MenuItem::section('menu.configuration'), MenuItem::linkToCrud('menu.themes', 'fas fa-th-large', Theme::class), MenuItem::linkToCrud('menu.categories', 'fas fa-list', Category::class), - MenuItem::section('Administration'), - MenuItem::linkToCrud('User', 'fas fa-user', User::class), - MenuItem::linkToCrud('Group', 'fas fa-users', Group::class), - MenuItem::linkToCrud('Import kørsler ', 'fas fa-file-excel', ImportRun::class), - MenuItem::linkToRoute('Eksport', 'fas fa-file-import', 'export_page'), - - MenuItem::section('LogOut '), - MenuItem::linkToRoute('Logout', 'fas fa-sign-out-alt', 'admin_logout'), + MenuItem::section('menu.administration'), + MenuItem::linkToCrud('menu.users', 'fas fa-user', User::class), + MenuItem::linkToCrud('menu.groups', 'fas fa-users', UserGroup::class), + MenuItem::linkToRoute('menu.exports', 'fas fa-file-import', 'export_page'), + MenuItem::linkToCrud('menu.import_runs', 'fas fa-file-excel', ImportRun::class), ]; } } diff --git a/src/Controller/Admin/AnswerController.php b/src/Controller/Admin/AnswerController.php index ac6d1bb3..9abfd86b 100644 --- a/src/Controller/Admin/AnswerController.php +++ b/src/Controller/Admin/AnswerController.php @@ -44,9 +44,10 @@ public function newAnswer( } if (isset($reportId)) { - $answer = $answerRepository->findOneBy( - ['question' => $questionId, 'report' => $reportId] - ); + $answer = $answerRepository->findOneBy([ + 'question' => $questionId, + 'report' => $reportId, + ]); if (!$answer) { $answer = new Answer(); @@ -56,9 +57,10 @@ public function newAnswer( } } if (isset($systemId)) { - $answer = $answerRepository->findOneBy( - ['question' => $questionId, 'system' => $systemId] - ); + $answer = $answerRepository->findOneBy([ + 'question' => $questionId, + 'system' => $systemId, + ]); if (!$answer) { $answer = new Answer(); @@ -70,14 +72,11 @@ public function newAnswer( $entityManager->flush(); - return $this->redirectToRoute( - 'app_admin_customdashboardcrud_index', - [ - 'crudAction' => 'edit', - 'entityId' => $answer->getId(), - 'referer' => $request->query->get('referer'), - 'crudControllerFqcn' => AnswerCrudController::class, - ] - ); + return $this->redirectToRoute('admin', [ + 'crudAction' => 'edit', + 'entityId' => $answer->getId(), + 'referer' => $request->query->get('referer'), + 'crudControllerFqcn' => AnswerCrudController::class, + ]); } } diff --git a/src/Controller/Admin/AnswerCrudController.php b/src/Controller/Admin/AnswerCrudController.php index 9e138cfa..a6f62fff 100644 --- a/src/Controller/Admin/AnswerCrudController.php +++ b/src/Controller/Admin/AnswerCrudController.php @@ -3,61 +3,108 @@ namespace App\Controller\Admin; use App\Entity\Answer; +use App\Entity\Question; +use App\Entity\System; use Doctrine\ORM\EntityManagerInterface; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; -use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; +use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\Translation\TranslatableMessage; class AnswerCrudController extends AbstractCrudController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + ) { + } + public static function getEntityFqcn(): string { return Answer::class; } - public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void + #[\Override] + protected function getRedirectResponseAfterSave(AdminContext $context, string $action): RedirectResponse + { + // Lifted from parent::getRedirectResponseAfterSave(). + $submitButtonName = $context->getRequest()->request->all()['ea']['newForm']['btn'] ?? null; + + // Answers don't have an index which is where EasyAdmin will return to by default on save. + // Therefore we return to somewhere else on save. + if (Action::SAVE_AND_RETURN === $submitButtonName) { + $request = $context->getRequest(); + + // Check if we have a “referer” (sic!) set. + if ($referer = $request->get('referer')) { + return $this->redirect($referer); + } + // Check if we have a “system” set. + if ($system = $request->get('system')) { + return $this->redirectToRoute('admin_system_detail', ['entityId' => $system]); + } + + // Use system index as fallback. + return $this->redirectToRoute('admin_system_index'); + } + + return parent::getRedirectResponseAfterSave($context, $action); + } + + #[\Override] + public function createEntity(string $entityFqcn): Answer { - parent::updateEntity($entityManager, $entityInstance); // TODO: Change the autogenerated stub + /** @var Answer $entity */ + $entity = parent::createEntity($entityFqcn); + + // Set system and question on new answers. + $params = $this->getContext()->getRequest()->query->all(); + if (isset($params['system'], $params['question'])) { + $system = $this->entityManager->getRepository(System::class)->find($params['system']); + $question = $this->entityManager->getRepository(Question::class)->find($params['question']); + if ($system && $question) { + $entity + ->setSystem($system) + ->setQuestion($question); + } else { + throw new BadRequestHttpException(); + } + } - $url = $this->generateUrl('dashboard', ['entityType' => 'system']); - $response = new RedirectResponse($url); - $response->send(); + return $entity; } + #[\Override] public function configureActions(Actions $actions): Actions { return $actions - - ->add(Crud::PAGE_EDIT, Action::EDIT) - ->add(Crud::PAGE_DETAIL, Action::DETAIL) - ->disable(Action::NEW, Action::DELETE, Action::INDEX) - ; + ->disable(Action::SAVE_AND_ADD_ANOTHER, Action::DELETE, Action::INDEX, Action::DETAIL); } /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { - $question = TextField::new('question')->setFormTypeOptions(['disabled' => true]); - $smiley = ChoiceField::new('smiley')->setChoices([ - 'GREEN' => 'GREEN', - 'RED' => 'RED', - 'BLUE' => 'BLUE', - 'YELLOW' => 'YELLOW', - ]); - $note = TextareaField::new('note'); - if (Crud::PAGE_EDIT === $pageName) { - return [$question, $smiley, $note]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$question, $smiley, $note]; - } else { - throw new \Exception('Invalid page: '.$pageName); - } + $question = TextField::new('question') + ->setFormTypeOptions(['disabled' => true]); + yield $question; + yield ChoiceField::new('smiley') + ->setTranslatableChoices([ + 'GREEN' => new TranslatableMessage('smiley.GREEN'), + 'RED' => new TranslatableMessage('smiley.RED'), + 'BLUE' => new TranslatableMessage('smiley.BLUE'), + 'YELLOW' => new TranslatableMessage('smiley.YELLOW'), + ]) + // We want to use fancy smileys in the options (cf. translations/messages.da.yml). + ->escapeHtml(false) + ; + yield TextareaField::new('note'); } } diff --git a/src/Controller/Admin/CategoryCrudController.php b/src/Controller/Admin/CategoryCrudController.php index f84e9496..0bc37c44 100644 --- a/src/Controller/Admin/CategoryCrudController.php +++ b/src/Controller/Admin/CategoryCrudController.php @@ -3,13 +3,13 @@ namespace App\Controller\Admin; use App\Entity\Category; +use App\Form\QuestionType; +use App\Form\ThemeCategoryType; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; -use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField; -use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\TimeField; @@ -20,40 +20,42 @@ public static function getEntityFqcn(): string return Category::class; } - public function configureActions(Actions $actions): Actions + #[\Override] + public function configureCrud(Crud $crud): Crud { - $actions - ->add(Crud::PAGE_INDEX, Action::DETAIL) - ; + return parent::configureCrud($crud) + // https://symfony.com/bundles/EasyAdminBundle/current/design.html#form-field-templates + ->addFormTheme('admin/form.html.twig'); + } - return parent::configureActions($actions); // TODO: Change the autogenerated stub + #[\Override] + public function configureActions(Actions $actions): Actions + { + return parent::configureActions($actions) + ->add(Crud::PAGE_INDEX, Action::DETAIL); } /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { - $id = IdField::new('id'); - $name = TextField::new('name'); - $created_by = TextField::new('created_by'); - $updated_by = TextField::new('updated_by'); - $number_of_questions = AssociationField::new('questions'); - $coll_question = CollectionField::new('questions')->setEntryType('App\Form\QuestionType'); - - $time_created_at = TimeField::new('created_at'); - $time_updated_at = TimeField::new('time_updated_at'); - - if (Crud::PAGE_INDEX === $pageName) { - return [$id, $name, $number_of_questions]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$id, $name, $coll_question, $created_by, $updated_by, $time_created_at, $time_updated_at]; - } elseif (Crud::PAGE_NEW === $pageName) { - return [$name, $coll_question]; - } elseif (Crud::PAGE_EDIT === $pageName) { - return [$name, $coll_question]; - } else { - throw new \Exception('Invalid page: '.$pageName); - } + yield TextField::new('name')->setLabel('entity.category.name'); + yield TextField::new('createdBy') + ->onlyOnDetail(); + yield TextField::new('updatedBy') + ->onlyOnDetail(); + yield TimeField::new('createdAt') + ->onlyOnDetail(); + yield TimeField::new('updatedAt') + ->onlyOnDetail(); + // See templates/admin/form.html.twig for details on how we show this as a table. + yield CollectionField::new('questions')->setLabel('entity.category.questions') + ->setTemplatePath(Crud::PAGE_DETAIL === $pageName ? 'admin/collection_plain.html.twig' : 'admin/collection.html.twig') + ->setEntryType(QuestionType::class) + ->renderExpanded(); + yield CollectionField::new('themeCategories')->setEntryType(ThemeCategoryType::class) + ->onlyOnDetail(); } } diff --git a/src/Controller/Admin/CustomDashboardCrudController.php b/src/Controller/Admin/CustomDashboardCrudController.php index 5f14b26e..7a98930b 100644 --- a/src/Controller/Admin/CustomDashboardCrudController.php +++ b/src/Controller/Admin/CustomDashboardCrudController.php @@ -2,80 +2,61 @@ namespace App\Controller\Admin; -use App\Entity\Group; use App\Entity\Report; -use App\Entity\SelfServiceAvailableFromItem; use App\Entity\System; -use App\Repository\CategoryRepository; -use App\Repository\ThemeCategoryRepository; -use Doctrine\Common\Collections\Collection; +use App\Entity\UserGroup; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\QueryBuilder; +use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard; use Knp\Component\Pager\PaginatorInterface; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Form\Extension\Core\Type\SubmitType; -use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Contracts\Translation\TranslatorInterface; +#[AdminDashboard(routePath: '/admin', routeName: 'admin')] class CustomDashboardCrudController extends AbstractSystatusDashboardController { - private $categoryRepository; - private $themeCategoryRepository; - protected $entityManager; - private $paginator; - protected $translator; + use EntityFilterTrait; /** * AdminController constructor. */ public function __construct( - CategoryRepository $categoryRepository, - ThemeCategoryRepository $themeCategoryRepository, - EntityManagerInterface $entityManager, - PaginatorInterface $paginator, - TranslatorInterface $translator, + private readonly EntityManagerInterface $entityManager, + private readonly PaginatorInterface $paginator, + private readonly TranslatorInterface $translator, ) { - $this->categoryRepository = $categoryRepository; - $this->themeCategoryRepository = $themeCategoryRepository; - $this->entityManager = $entityManager; - $this->paginator = $paginator; - $this->translator = $translator; } - #[Route('admin/{entityType}', name: 'dashboard')] - public function dashboard(Request $request, $entityType): mixed + /** + * Redirect /admin to the reports page to hide easyAdmin's default front page. + */ + #[Route(path: '/dashboard')] + #[\Override] + public function index(): Response { - $queryParameters = $request->query; - $queryParams = $request->query->all(); // Fetch all query parameters as an array. - $formData = $queryParams['form'] ?? []; // Safely retrieve 'form' as an array. - - // Ensure `formData` is always an array. - if (!is_array($formData)) { - $formData = []; - } + return $this->redirectToRoute('dashboard', ['entityType' => 'report']); + } - $formParameters = array_merge([ - 'groups' => [], - 'subowner' => '', - 'theme' => '', - 'category' => '', - 'self_service' => '', - 'search' => '', - ], $formData); + /** + * @throws \Exception + */ + #[Route(path: '/dashboard/{entityType}', name: 'dashboard')] + public function dashboard(Request $request, string $entityType): Response + { + $queryParameters = $request->query; - $userGroups = $this->entityManager->getRepository(Group::class)->findAll(); - $userGroupsThemesAndCategories = $this->getUserGroupsThemesAndCategories($userGroups ?: [], $entityType); + $filterParameters = $this->getFilterParameters($request); + $userGroups = $this->entityManager + ->getRepository(UserGroup::class) + ->findAll(); // Get a query for the entity type. $repository = $this->getRepository($entityType); $query = $repository->createQueryBuilder('e'); - $query = $this->applyFilters($query, $formParameters, $entityType); - - // Get sub owners if a group has been selected. - $subOwnerOptions = $this->getSubOwnerOptions($repository, $formParameters['groups']); + $query = $this->applyFilters($query, $filterParameters, $this->getEntityClassName($entityType)); $paginator = $this->paginator->paginate( $query, @@ -86,20 +67,25 @@ public function dashboard(Request $request, $entityType): mixed $availableCategories = []; $themes = []; - if (!empty($formParameters['groups'])) { - $groups = $this->entityManager->getRepository(Group::class)->findBy([ - 'id' => $formParameters['groups'], - ]); + if (!empty($filterParameters['groups'])) { + $groups = $this->entityManager + ->getRepository(UserGroup::class) + ->findBy([ + 'id' => $filterParameters['groups'], + ]); } else { $groups = $userGroups; } foreach ($groups as $group) { - $groupThemes = 'report' == $entityType ? $group->getReportThemes() : $group->getSystemThemes(); + $groupThemes = + 'report' == $entityType + ? $group->getReportThemes() + : $group->getSystemThemes(); foreach ($groupThemes as $theme) { - if ('' != $formParameters['theme']) { - if ($theme->getId() != $formParameters['theme']) { + if ('' != $filterParameters['theme']) { + if ($theme->getId() != $filterParameters['theme']) { continue; } } @@ -108,8 +94,11 @@ public function dashboard(Request $request, $entityType): mixed $themes[$theme->getId()] = $theme; foreach ($theme->getOrderedCategories() as $category) { - if ('' != $formParameters['category']) { - if ($category->getId() != $formParameters['category']) { + if ('' != $filterParameters['category']) { + if ( + $category->getId() != + $filterParameters['category'] + ) { continue; } } @@ -120,274 +109,129 @@ public function dashboard(Request $request, $entityType): mixed } } - $selfServiceOptions = $this->getSelfServiceOptions($entityType); - - $filterFormBuilder = $this->getFilterFormBuilder($userGroupsThemesAndCategories, $formParameters, $subOwnerOptions, true, true, $selfServiceOptions); - $filterFormBuilder->setMethod('GET')->setAction($this->generateUrl('dashboard', ['entityType' => $entityType])); + $filterFormBuilder = $this->createFilterFormBuilder() + ->setAction( + $this->generateUrl('dashboard', ['entityType' => $entityType]) + ); + + $this->buildCustomFilters( + $request, + $this->getEntityClassName($entityType), + $filterFormBuilder, + filterThemes: true, + filterCategories: true + ); return $this->render('dashboard.html.twig', [ 'paginator' => $paginator, 'categories' => $availableCategories, - 'filters' => $filterFormBuilder->getForm()->createView(), + 'custom_filters' => $filterFormBuilder->getForm()->createView(), 'entityType' => $entityType, ]); } - private function getUserGroupsThemesAndCategories(array $userGroups, $entityType) - { - return array_reduce($userGroups, - function ($carry, Group $group) use ($entityType) { - $carry['groups'][$group->getId()] = $group->getName(); - - $groupThemes = 'report' == $entityType ? $group->getReportThemes() : $group->getSystemThemes(); - - foreach ($groupThemes as $theme) { - $carry['themes'][$theme->getId()] = $theme->getName(); - - foreach ($theme->getOrderedCategories() as $category) { - $carry['categories'][$category->getId()] = $category->getName(); - } - } - - return $carry; - }, [ - 'groups' => [], - 'themes' => [], - 'categories' => [], - ]); - } - /** * Get repository for entity type. + * + * @return EntityRepository */ - private function getRepository($entityType): ?EntityRepository + private function getRepository( + string $entityType, + ): EntityRepository { + $className = $this->getEntityClassName($entityType); + + return $this->entityManager->getRepository($className); + } + + private function getEntityClassName(string $entityType): ?string { return match ($entityType) { - 'system' => $this->entityManager->getRepository(System::class), - 'report' => $this->entityManager->getRepository(Report::class), + 'system' => System::class, + 'report' => Report::class, default => null, }; } /** - * Apply common filters for report and system query. + * Get sub-owners for selected group. */ - private function applyFilters( - QueryBuilder $query, - array $formParameters, - $entityType = null, - ): QueryBuilder { - $query->andWhere('e.archivedAt IS NULL'); - - // Filter inactives out. - if ('report' == $entityType) { - $query->andWhere('e.sysStatus = \'Aktiv\''); - } elseif ('system' == $entityType) { - $query->andWhere('e.sysStatus <> \'Systemet bruges ikke længere\''); - } - - // Get the groups the user can search in. - if (!empty($formParameters['groups'])) { - $groups = $this->entityManager->getRepository(Group::class)->findBy([ - 'id' => $formParameters['groups'], - ]); - - foreach ($groups as $group) { - $query->andWhere($query->expr()->isMemberOf(':group'.$group->getId(), 'e.groups')); - $query->setParameter(':group'.$group->getId(), $group); - } - } - - if (isset($formParameters['self_service']) && '' != $formParameters['self_service']) { - $item = $this->entityManager->getRepository(SelfServiceAvailableFromItem::class)->findOneBy([ - 'id' => $formParameters['self_service'], + private function getSubOwnerOptions( + mixed $repository, + mixed $selectedGroups, + ): mixed { + $groups = $this->entityManager + ->getRepository(UserGroup::class) + ->findBy([ + 'id' => $selectedGroups, ]); - if (null != $item) { - $query->andWhere(':self_service MEMBER OF e.selfServiceAvailableFromItems'); - $query->setParameter('self_service', $item); - } - } - - if (isset($formParameters['search']) && '' != $formParameters['search']) { - $query->andWhere('e.name LIKE :name'); - $query->setParameter('name', '%'.$formParameters['search'].'%'); - } - - if (isset($formParameters['subowner']) && '' != $formParameters['subowner']) { - $query->andWhere('e.sysOwnerSub = :subowner'); - $query->setParameter('subowner', $formParameters['subowner']); - } - - return $query; - } - - /** - * Get subowners for selected group. - */ - private function getSubOwnerOptions($repository, $selectedGroups): mixed - { - $groups = $this->entityManager->getRepository(Group::class)->findBy([ - 'id' => $selectedGroups, - ]); $subOwnersQueryBuilder = $repository->createQueryBuilder('e'); $subOwnersQueryBuilder->select('DISTINCT e.sysOwnerSub'); $subOwnersQueryBuilder->andWhere('e.sysOwnerSub IS NOT NULL'); - // Filter inactives out. - $subOwnersQueryBuilder->andWhere('e.archivedAt IS NULL'); - - $class = $repository->getClassName(); - if (Report::class === $class) { - $subOwnersQueryBuilder->andWhere('e.sysStatus = \'Aktiv\''); - } elseif (System::class === $class) { - $subOwnersQueryBuilder->andWhere('e.sysStatus <> \'Systemet bruges ikke længere\''); - } - foreach ($groups as $group) { - $subOwnersQueryBuilder->andWhere($subOwnersQueryBuilder->expr()->isMemberOf(':group'.$group->getId(), 'e.groups')); - $subOwnersQueryBuilder->setParameter(':group'.$group->getId(), $group); + $subOwnersQueryBuilder->andWhere( + $subOwnersQueryBuilder + ->expr() + ->isMemberOf(':group'.$group->getId(), 'e.groups') + ); + $subOwnersQueryBuilder->setParameter( + ':group'.$group->getId(), + $group + ); } $subOwners = $subOwnersQueryBuilder->getQuery()->getResult(); - return array_reduce($subOwners, + return array_reduce( + $subOwners, function ($carry, $item) { $carry[$item['sysOwnerSub']] = $item['sysOwnerSub']; return $carry; - }, []); - } - - /** - * Get options for self service filter. - */ - private function getSelfServiceOptions($entityType): array - { - $selfServiceOptions = []; - if ('system' == $entityType) { - /* @var Collection $selfServiceAvailableFromItems */ - $selfServiceAvailableFromItems = $this->entityManager->getRepository(SelfServiceAvailableFromItem::class)->findAll(); - /* @var SelfServiceAvailableFromItem $item */ - foreach ($selfServiceAvailableFromItems as $item) { - $selfServiceOptions[$item->getName()] = $item->getId(); - } - } - - return $selfServiceOptions; - } - - /** - * Get filter form builder. - */ - private function getFilterFormBuilder( - $userGroupsThemesAndCategories, - $formParameters, - $subownerOptions, - bool $filterThemes = false, - bool $filterCategories = false, - array $filterSelfServiceOptions = [], - ): \Symfony\Component\Form\FormBuilderInterface { - $filterFormBuilder = $this->createFormBuilder(); - $filterFormBuilder->add('groups', ChoiceType::class, [ - 'label' => 'filter.groups', - 'placeholder' => 'filter.placeholder.groups', - 'choices' => array_flip($userGroupsThemesAndCategories['groups']), - 'multiple' => true, - 'attr' => [ - 'class' => 'form-control', - 'data-placeholder' => $this->translator->trans('filter.placeholder.groups'), - ], - 'required' => false, - 'data' => $formParameters['groups'] ?? null, - ]); - $filterFormBuilder->add('subowner', ChoiceType::class, [ - 'label' => 'filter.subowner', - 'placeholder' => 'filter.placeholder.subowner', - 'choices' => $subownerOptions, - 'attr' => [ - 'class' => 'form-control', - ], - 'required' => false, - 'disabled' => 0 == count($subownerOptions), - 'data' => $formParameters['subowner'] ?? null, - ]); - if ($filterThemes) { - $filterFormBuilder->add('theme', ChoiceType::class, [ - 'label' => 'filter.theme', - 'placeholder' => 'filter.placeholder.theme', - 'choices' => array_flip($userGroupsThemesAndCategories['themes']), - 'attr' => [ - 'class' => 'form-control', - ], - 'required' => false, - 'data' => $formParameters['theme'] ?? null, - ]); - } - if ($filterCategories) { - $filterFormBuilder->add('category', ChoiceType::class, [ - 'label' => 'filter.category', - 'placeholder' => 'filter.placeholder.category', - 'choices' => array_flip($userGroupsThemesAndCategories['categories']), - 'attr' => [ - 'class' => 'form-control', - ], - 'required' => false, - 'data' => $formParameters['category'] ?? null, - ]); - } - if (count($filterSelfServiceOptions) > 0) { - $filterFormBuilder->add('self_service', ChoiceType::class, [ - 'label' => 'filter.self_service', - 'placeholder' => 'filter.placeholder.self_service', - 'choices' => $filterSelfServiceOptions, - 'attr' => [ - 'class' => 'form-control', - ], - 'required' => false, - 'data' => $formParameters['self_service'] ?? null, - ]); - } - $filterFormBuilder->add('search', TextType::class, [ - 'label' => 'filter.search', - 'attr' => [ - 'class' => 'form-control', - 'placeholder' => 'filter.placeholder.search', - ], - 'required' => false, - 'data' => $formParameters['search'] ?? null, - ]); - $filterFormBuilder->add('save', SubmitType::class, [ - 'label' => 'filter.submit', - ]); - - return $filterFormBuilder; + }, + [] + ); } /** * Overrides EasyAdmin show action. * - * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * @return RedirectResponse|Response */ - public function showAction() + public function show(): RedirectResponse|Response { $entityArray = $this->entity; - if (Report::class == $entityArray['class'] || System::class == $entityArray['class']) { + if ( + Report::class == $entityArray['class'] + || System::class == $entityArray['class'] + ) { $entity = $this->getEntity($entityArray['class'], $_GET['id']); $accessGranted = $this->isGranted('show', $entity); if (!$accessGranted) { - $this->addFlash('error', $this->translator->trans('flash.access_denied')); - - return $this->redirectToRoute('list', ['entityType' => strtolower($entityArray['name'])]); + $this->addFlash( + 'error', + $this->translator->trans('flash.access_denied') + ); + + return $this->redirectToRoute('list', [ + 'entityType' => strtolower((string) $entityArray['name']), + ]); } } return parent::showAction(); } - private function getEntity($className, $id): ?object + /** + * @param string $entityName + * @param mixed $id + * + * @return object|null + */ + private function getEntity(string $entityName, mixed $id): ?object { - return $this->entityManager->getRepository($className)->find($id); + return $this->entityManager->getRepository($entityName)->find($id); } } diff --git a/src/Controller/Admin/EntityFilterTrait.php b/src/Controller/Admin/EntityFilterTrait.php new file mode 100644 index 00000000..d29e0c33 --- /dev/null +++ b/src/Controller/Admin/EntityFilterTrait.php @@ -0,0 +1,312 @@ +createFormBuilder(options: ['csrf_protection' => false]) + ->setMethod(Request::METHOD_GET); + } + + protected function buildCustomFilters( + Request $request, + string $entityType, + FormBuilderInterface $builder, + bool $filterThemes = false, + bool $filterCategories = false, + ): void { + $userGroups = $this->entityManager->getRepository(UserGroup::class)->findAll(); + $userGroupsThemesAndCategories = $this->getUserGroupsThemesAndCategories($userGroups, $entityType); + + $formParameters = array_merge([ + 'groups' => [], + 'subowner' => '', + 'search' => '', + ], $request->get('form') ?: []); + + $repository = $this->entityManager->getRepository($entityType); + // Get sub owners if a group has been selected. + $subOwnerOptions = $this->getSubOwnerOptions($repository, $formParameters['groups']); + + $filterSelfServiceOptions = $this->getSelfServiceOptions($entityType); + + $placeholder = $this->translator->trans('filter.placeholder.groups'); + $builder->add('groups', ChoiceType::class, [ + 'label' => 'filter.groups', + 'placeholder' => $placeholder, + 'choices' => array_flip($userGroupsThemesAndCategories['groups']), + 'multiple' => true, + 'attr' => [ + // @todo Find documentation reference for why setting data-ea-widget actually works + // (https://github.com/search?q=repo%3AEasyCorp%2FEasyAdminBundle%20data-ea-widget&type=code) + 'data-ea-widget' => 'ea-autocomplete', + 'data-placeholder' => $placeholder, + ], + 'required' => false, + 'data' => $formParameters['groups'] ?? null, + ]); + + $placeholder = $this->translator->trans('filter.placeholder.subowner'); + $builder->add('subowner', ChoiceType::class, [ + 'label' => 'filter.subowner', + 'placeholder' => 'filter.placeholder.subowner', + 'choices' => $subOwnerOptions, + 'attr' => [ + 'data-ea-widget' => 'ea-autocomplete', + 'data-placeholder' => $placeholder, + ], + 'required' => false, + 'disabled' => empty($subOwnerOptions), + 'data' => $formParameters['subowner'] ?? null, + ]); + + if ($filterThemes) { + $placeholder = $this->translator->trans('filter.placeholder.theme'); + $builder->add('theme', ChoiceType::class, [ + 'label' => 'filter.theme', + 'placeholder' => $placeholder, + 'choices' => array_flip($userGroupsThemesAndCategories['themes']), + 'attr' => [ + 'data-ea-widget' => 'ea-autocomplete', + 'data-placeholder' => $placeholder, + ], + 'required' => false, + 'data' => $formParameters['theme'] ?? null, + ]); + } + if ($filterCategories) { + $placeholder = $this->translator->trans('filter.placeholder.category'); + $builder->add('category', ChoiceType::class, [ + 'label' => 'filter.category', + 'placeholder' => $placeholder, + 'choices' => array_flip($userGroupsThemesAndCategories['categories']), + 'attr' => [ + 'data-ea-widget' => 'ea-autocomplete', + 'data-placeholder' => $placeholder, + ], + 'required' => false, + 'data' => $formParameters['category'] ?? null, + ]); + } + if (count($filterSelfServiceOptions) > 0) { + $placeholder = $this->translator->trans('filter.placeholder.self_service'); + $builder->add('self_service', ChoiceType::class, [ + 'label' => 'filter.self_service', + 'placeholder' => $placeholder, + 'choices' => $filterSelfServiceOptions, + 'attr' => [ + 'data-ea-widget' => 'ea-autocomplete', + 'data-placeholder' => $placeholder, + ], + 'required' => false, + 'data' => $formParameters['self_service'] ?? null, + ]); + } + + $placeholder = $this->translator->trans('filter.placeholder.search'); + $builder->add('search', TextType::class, [ + 'label' => 'filter.search', + 'attr' => [ + 'placeholder' => $placeholder, + ], + 'required' => false, + 'data' => $formParameters['search'] ?? null, + ]); + $builder->add('save', SubmitType::class, [ + 'label' => 'filter.submit', + ]); + } + + /** + * Get array of a user's groups, themes and categories. + * + * @param UserGroup[] $userGroups + * + * @return mixed + */ + private function getUserGroupsThemesAndCategories(array $userGroups, string $entityType) + { + return array_reduce($userGroups, + function ($carry, UserGroup $group) use ($entityType) { + $carry['groups'][$group->getId()] = $group->getName(); + + $groupThemes = 'report' == $entityType ? $group->getReportThemes() : $group->getSystemThemes(); + + foreach ($groupThemes as $theme) { + $carry['themes'][$theme->getId()] = $theme->getName(); + + foreach ($theme->getOrderedCategories() as $category) { + $carry['categories'][$category->getId()] = $category->getName(); + } + } + + return $carry; + }, [ + 'groups' => [], + 'themes' => [], + 'categories' => [], + ]); + } + + /** + * Get subowners for selected group. + * + * @param EntityRepository $repository + * @param UserGroup[] $selectedGroups + * + * @return mixed + */ + private function getSubOwnerOptions(EntityRepository $repository, array $selectedGroups) + { + $groups = $this->entityManager->getRepository(UserGroup::class)->findBy([ + 'id' => $selectedGroups, + ]); + + $subOwnersQueryBuilder = $repository->createQueryBuilder('e'); + $subOwnersQueryBuilder->select('DISTINCT e.sysOwnerSub'); + $subOwnersQueryBuilder->andWhere('e.sysOwnerSub IS NOT NULL'); + + foreach ($groups as $group) { + $subOwnersQueryBuilder->andWhere($subOwnersQueryBuilder->expr()->isMemberOf(':group'.$group->getId(), 'e.groups')); + $subOwnersQueryBuilder->setParameter(':group'.$group->getId(), $group); + } + + $subOwners = $subOwnersQueryBuilder->getQuery()->getResult(); + + return array_reduce($subOwners, + function ($carry, $item) { + $carry[$item['sysOwnerSub']] = $item['sysOwnerSub']; + + return $carry; + }, []); + } + + /** + * Get options for self service filter. + * + * @return array + */ + private function getSelfServiceOptions(string $entityType): array + { + $selfServiceOptions = []; + if (System::class === $entityType) { + /* @var \Doctrine\Common\Collections\Collection $selfServiceAvailableFromItems */ + $selfServiceAvailableFromItems = $this->entityManager->getRepository(SelfServiceAvailableFromItem::class)->findAll(); + /* @var SelfServiceAvailableFromItem $item */ + foreach ($selfServiceAvailableFromItems as $item) { + $selfServiceOptions[$item->getName()] = $item->getId(); + } + } + + return $selfServiceOptions; + } + + /** + * @return array + */ + private function getFilterParameters(Request $request): array + { + $formData = (array) ($request->query->all()['form'] ?? null); + + return array_merge( + [ + 'groups' => [], + 'subowner' => '', + 'theme' => '', + 'category' => '', + 'self_service' => '', + 'search' => '', + ], + $formData + ); + } + + /** + * Apply common filters for report and system query. + * + * @param QueryBuilder $query + * @param array $filterParameters + * @param string|null $entityType + * + * @return QueryBuilder + */ + private function applyFilters( + QueryBuilder $query, + array $filterParameters, + ?string $entityType = null, + ?string $alias = null, + ): QueryBuilder { + $alias ??= $query->getRootAliases()[0]; + if (empty($alias)) { + throw new \RuntimeException('Cannot get root alias for query'); + } + + // Get the groups the user can search in. + if (!empty($filterParameters['groups'])) { + $groups = $this->entityManager + ->getRepository(UserGroup::class) + ->findBy([ + 'id' => $filterParameters['groups'], + ]); + + foreach ($groups as $group) { + $query->andWhere( + $query + ->expr() + ->isMemberOf(':group'.$group->getId(), $alias.'.groups') + ); + $query->setParameter(':group'.$group->getId(), $group); + } + } + + if ( + isset($filterParameters['self_service']) + && '' != $filterParameters['self_service'] + ) { + $item = $this->entityManager + ->getRepository(SelfServiceAvailableFromItem::class) + ->findOneBy([ + 'id' => $filterParameters['self_service'], + ]); + if (null != $item) { + $query->andWhere( + ':self_service MEMBER OF '.$alias.'.selfServiceAvailableFromItems' + ); + $query->setParameter('self_service', $item); + } + } + + if ( + isset($filterParameters['search']) + && '' != $filterParameters['search'] + ) { + $query->andWhere($alias.'.name LIKE :name'); + $query->setParameter('name', '%'.$filterParameters['search'].'%'); + } + + if ( + isset($filterParameters['subowner']) + && '' != $filterParameters['subowner'] + ) { + $query->andWhere($alias.'.sysOwnerSub = :subowner'); + $query->setParameter('subowner', $filterParameters['subowner']); + } + + return $query; + } +} diff --git a/src/Controller/Admin/GroupCrudController.php b/src/Controller/Admin/GroupCrudController.php index bbda96e9..27b7f580 100644 --- a/src/Controller/Admin/GroupCrudController.php +++ b/src/Controller/Admin/GroupCrudController.php @@ -2,7 +2,7 @@ namespace App\Controller\Admin; -use App\Entity\Group; +use App\Entity\UserGroup; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; @@ -10,59 +10,53 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; -use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; -use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; +use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; +use Symfony\Component\Translation\TranslatableMessage; class GroupCrudController extends AbstractCrudController { public static function getEntityFqcn(): string { - return Group::class; + return UserGroup::class; } + #[\Override] public function configureActions(Actions $actions): Actions { - $actions - ->add(Crud::PAGE_INDEX, Action::DETAIL) - ->remove(Crud::PAGE_INDEX, Action::DELETE) - ; + return parent::configureActions($actions) + ->add(Crud::PAGE_INDEX, Action::DETAIL); + } - return $actions; + #[\Override] + public function configureCrud(Crud $crud): Crud + { + return parent::configureCrud($crud) + ->setEntityLabelInSingular(new TranslatableMessage('UserGroup')) + ->setEntityLabelInPlural(new TranslatableMessage('UserGroups')) + ; } /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { - $id = IdField::new('id'); - $name = TextField::new('name'); - $roles = ArrayField::new('roles'); - $system = ArrayField::new('systems'); - $report = ArrayField::new('reports'); - $systemtheme = ArrayField::new('systemThemes'); - $reporttheme = ArrayField::new('reportTheme'); - $users = IntegerField::new('users'); - - $asoc_report = AssociationField::new('reports'); - $asoc_systems = AssociationField::new('systems'); - - $choice_roles = ChoiceField::new('roles')->setChoices([ + yield TextField::new('name'); + yield ChoiceField::new('roles')->setChoices([ 'User' => 'ROLE_USER', 'Admin' => 'ROLE_ADMIN', - ])->allowMultipleChoices(true)->renderExpanded()->setEmptyData(false); - - if (Crud::PAGE_INDEX === $pageName) { - return [$name, $asoc_report, $asoc_systems]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$id, $name, $roles, $system, $report, $systemtheme, $reporttheme, $users]; - } elseif (Crud::PAGE_NEW === $pageName) { - return [$name, $choice_roles]; - } elseif (Crud::PAGE_EDIT === $pageName) { - return [$id, $name, $roles]; - } else { - throw new \Exception('Invalid page: '.$pageName); - } + ])->allowMultipleChoices()->renderExpanded()->setEmptyData(false); + yield CollectionField::new('reports') + ->setTemplatePath('admin/collection.html.twig'); + yield AssociationField::new('systems') + ->setTemplatePath('admin/collection.html.twig'); + yield ArrayField::new('systemThemes') + ->setTemplatePath('admin/collection.html.twig'); + yield ArrayField::new('reportThemes') + ->setTemplatePath('admin/collection.html.twig'); + yield ArrayField::new('users') + ->setTemplatePath('admin/collection.html.twig'); } } diff --git a/src/Controller/Admin/ImportRunCrudController.php b/src/Controller/Admin/ImportRunCrudController.php index 34a9b80b..58ce2c10 100644 --- a/src/Controller/Admin/ImportRunCrudController.php +++ b/src/Controller/Admin/ImportRunCrudController.php @@ -19,6 +19,7 @@ public static function getEntityFqcn(): string return ImportRun::class; } + #[\Override] public function configureActions(Actions $actions): Actions { $actions @@ -32,6 +33,7 @@ public function configureActions(Actions $actions): Actions /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { $id = IdField::new('id'); diff --git a/src/Controller/Admin/QuestionCrudController.php b/src/Controller/Admin/QuestionCrudController.php index f60af3a4..5cb399ab 100644 --- a/src/Controller/Admin/QuestionCrudController.php +++ b/src/Controller/Admin/QuestionCrudController.php @@ -16,6 +16,7 @@ public static function getEntityFqcn(): string return Question::class; } + #[\Override] public function configureActions(Actions $actions): Actions { return $actions @@ -28,6 +29,7 @@ public function configureActions(Actions $actions): Actions /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { $id = IdField::new('id')->setLabel('entity.system.id'); diff --git a/src/Controller/Admin/ReportCrudController.php b/src/Controller/Admin/ReportCrudController.php index 84a63991..4a658662 100644 --- a/src/Controller/Admin/ReportCrudController.php +++ b/src/Controller/Admin/ReportCrudController.php @@ -6,22 +6,24 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; -use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField; use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField; use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; +use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\UrlField; +use Symfony\Component\Translation\TranslatableMessage; -class ReportCrudController extends AbstractCrudController +class ReportCrudController extends AbstractFilterableCrudController { public static function getEntityFqcn(): string { return Report::class; } + #[\Override] public function configureActions(Actions $actions): Actions { $actions @@ -32,70 +34,91 @@ public function configureActions(Actions $actions): Actions return $actions; } + #[\Override] public function configureFields(string $pageName): iterable { - $title = TextField::new('sys_title')->setLabel('entity.report.sys_title'); - $title2 = $title->setFormTypeOption('disabled', 'disabled'); - $internalId = IdField::new('sys_internal_id')->setLabel('entity.report.sys_internal_id'); - $edocUrl = UrlField::new('edoc_url')->setLabel('entity.report.edoc_url'); - $sys_link = UrlField::new('sys_link')->setLabel('entity.report.sys_link'); - $name = TextField::new('name')->setLabel('entity.report.name'); - $text = TextField::new('text')->setLabel('entity.report.text'); - $systemOwner = TextField::new('sys_system_owner')->setLabel('entity.report.sys_system_owner'); - $groups = AssociationField::new('groups')->setLabel('entity.report.groups'); + switch ($pageName) { + case Crud::PAGE_INDEX: + // Cf. https://github.com/itk-dev/sysstatus/blob/5383a3a566ce316c338441ed826ecf3fdcf98815/src/Controller/AdminController.php#L263-L288 + yield IdField::new('id')->setLabel('entity.report.sys_id'); + yield TextField::new('sysTitle')->setLabel('entity.report.sys_title'); + yield CollectionField::new('groups')->setLabel('entity.report.groups') + ->renderExpanded(); + yield TextField::new('sysOwnerSub')->setLabel('entity.report.sys_owner_sub'); + yield TextField::new('sysSystemOwner')->setLabel('entity.report.sys_system_owner'); + yield UrlField::new('sysLink')->setLabel('entity.report.sys_link') + ->formatValue(static fn ($value) => new TranslatableMessage('Link')); + yield BooleanField::new('textSet')->setLabel('entity.report.text') + ->renderAsSwitch(false) + ->hideValueWhenFalse(); - $answerarea = CollectionField::new('answerarea')->setTemplatePath('easy_admin_overrides/answers_show.html.twig')->setLabel('Smileys'); - $answerarea = CollectionField::new('answerarea')->setTemplatePath('easy_admin_overrides/answers_show.html.twig')->setLabel('Smileys'); + return; - $alternativeTitle = TextField::new('sys_alternative_title')->setLabel('entity.report.sys_alternative_title'); - $sys_updated = DateTimeField::new('sys_updated')->setLabel('entity.report.sys_updated'); - $owner = TextField::new('sys_owner')->setLabel('entity.report.sys_owner'); - $afdeling = TextField::new('sys_owner_sub')->setLabel('entity.report.sys_owner'); - $confidentialInformation = BooleanField::new('sys_confidential_information')->setLabel('entity.report.sys_confidential_information'); - $purpose = TextField::new('sys_purpose')->setLabel('entity.report.sys_purpose'); - $classification = TextField::new('sys_classification')->setLabel('entity.report.sys_classification'); - $dateForRevision = DateTimeField::new('sys_date_for_revision')->setLabel('entity.report.sys_date_for_revision'); - $persons = TextField::new('sys_persons')->setLabel('entity.report.sys_persons'); - $informationTypes = TextField::new('sys_information_types')->setLabel('entity.report.sys_information_types'); - $dataSentTo = TextField::new('sys_data_sent_to')->setLabel('entity.report.sys_data_sent_to'); - $dataComeFrom = TextField::new('sys_data_come_from')->setLabel('entity.report.sys_data_come_from'); - $dataLocation = TextField::new('sys_data_location')->setLabel('entity.report.sys_data_location'); - $deletionDate = TextField::new('sys_latest_deletion_date')->setLabel('entity.report.sys_latest_deletion_date'); - $dataWorthSaving = TextField::new('sys_data_worth_saving')->setLabel('entity.report.sys_data_worth_saving'); - $dataProcessors = TextField::new('sys_data_processors')->setLabel('entity.report.sys_data_processors'); - $dataProcessingAgreement = TextField::new('sys_data_processing_agreement')->setLabel('entity.report.sys_data_processing_agreement'); - $dataProcessingAgreementLink = TextField::new('sys_data_processing_agreement_link')->setLabel('entity.report.sys_data_processing_agreement_link'); - $auditorStatement = TextField::new('sys_auditor_statement')->setLabel('entity.report.sys_auditor_statement'); - $auditorStatementLink = TextField::new('sys_auditor_statement_link')->setLabel('entity.report.sys_auditor_statement_link'); - $dataToScience = TextField::new('sys_data_to_science')->setLabel('entity.report.sys_data_to_science'); - $usage = TextField::new('sys_usage')->setLabel('entity.report.sys_usage'); - $requestForInsight = TextField::new('sys_request_for_insight')->setLabel('entity.report.sys_request_for_insight'); - $dateUse = DateTimeField::new('sys_date_use')->setLabel('entity.report.sys_date_use'); - $status = TextField::new('sys_status')->setLabel('entity.report.sys_status'); - $remarks = TextField::new('sys_remarks')->setLabel('entity.report.sys_remarks'); - $internalInformation = TextField::new('sys_internal_information')->setLabel('entity.report.sys_internal_information'); - $obligationToInform = TextField::new('sys_obligation_to_inform')->setLabel('entity.report.sys_obligation_to_inform'); - $legalBasis = TextField::new('sys_legal_basis')->setLabel('entity.report.sys_legal_basis'); - $consent = TextField::new('sys_consent')->setLabel('entity.report.sys_consent'); - $impactAnalysis = TextField::new('sys_impact_analysis')->setLabel('entity.report.sys_impact_analysis'); - $impactAnalysisLink = TextField::new('sys_impact_analysis_link')->setLabel('entity.report.sys_impact_analysis_link'); - $authorizationProcedure = TextField::new('sys_authorization_procedure')->setLabel('entity.report.sys_authorization_procedure'); - $version = TextField::new('sys_version')->setLabel('entity.report.sys_version'); + case Crud::PAGE_DETAIL: + // Cf. https://github.com/itk-dev/sysstatus/blob/5383a3a566ce316c338441ed826ecf3fdcf98815/config/packages/easy_admin.yaml#L100-L143 + yield TextField::new('sysTitle')->setLabel('entity.report.sys_title'); + yield IdField::new('sysInternalId')->setLabel('entity.report.sys_internal_id'); + yield UrlField::new('eDocUrl')->setLabel('entity.report.edoc_url'); + yield UrlField::new('sysLink')->setLabel('entity.report.sys_link'); + yield TextField::new('name')->setLabel('entity.report.name'); + yield TextEditorField::new('text')->setLabel('entity.report.text') + // Show raw value + ->setTemplatePath('admin/text_editor.raw.html.twig'); + yield TextField::new('sysSystemOwner')->setLabel('entity.report.sys_system_owner'); + // @todo Add links to each group? + yield CollectionField::new('groups')->setLabel('entity.report.groups'); + yield CollectionField::new('answerArea')->setLabel('entity.report.answers') + ->setTemplatePath('easy_admin_overrides/answers_show.html.twig'); + yield TextField::new('sysAlternativeTitle')->setLabel('entity.report.sys_alternative_title'); + yield DateTimeField::new('sysUpdated')->setLabel('entity.report.sys_updated'); + yield TextField::new('sysOwner')->setLabel('entity.report.sys_owner'); + yield BooleanField::new('sysConfidentialInformation')->setLabel('entity.report.sys_confidential_information'); + yield TextField::new('sysPurpose')->setLabel('entity.report.sys_purpose'); + yield TextField::new('sysClassification')->setLabel('entity.report.sys_classification'); + yield DateTimeField::new('sysDateForRevision')->setLabel('entity.report.sys_date_for_revision'); + yield TextField::new('sysPersons')->setLabel('entity.report.sys_persons'); + yield TextField::new('sysInformationTypes')->setLabel('entity.report.sys_information_types'); + yield TextField::new('sysDataSentTo')->setLabel('entity.report.sys_data_sent_to'); + yield TextField::new('sysDataComeFrom')->setLabel('entity.report.sys_data_come_from'); + yield TextField::new('sysDataLocation')->setLabel('entity.report.sys_data_location'); + yield TextField::new('sysLatestDeletionDate')->setLabel('entity.report.sys_latest_deletion_date'); + yield TextField::new('sysDataWorthSaving')->setLabel('entity.report.sys_data_worth_saving'); + yield TextField::new('sysDataProcessors')->setLabel('entity.report.sys_data_processors'); + yield TextField::new('sysDataProcessingAgreement')->setLabel('entity.report.sys_data_processing_agreement'); + yield TextField::new('sysDataProcessingAgreementLink')->setLabel('entity.report.sys_data_processing_agreement_link'); + yield TextField::new('sysAuditorStatement')->setLabel('entity.report.sys_auditor_statement'); + yield TextField::new('sysAuditorStatementLink')->setLabel('entity.report.sys_auditor_statement_link'); + yield TextField::new('sysDataToScience')->setLabel('entity.report.sys_data_to_science'); + yield TextField::new('sysUsage')->setLabel('entity.report.sys_usage'); + yield TextField::new('sysRequestForInsight')->setLabel('entity.report.sys_request_for_insight'); + yield DateTimeField::new('sysDateUse')->setLabel('entity.report.sys_date_use'); + yield TextField::new('sysStatus')->setLabel('entity.report.sys_status'); + yield TextField::new('sysRemarks')->setLabel('entity.report.sys_remarks'); + yield TextField::new('sysInternalInformation')->setLabel('entity.report.sys_internal_information'); + yield TextField::new('sysObligationToInform')->setLabel('entity.report.sys_obligation_to_inform'); + yield TextField::new('sysLegalBasis')->setLabel('entity.report.sys_legal_basis'); + yield TextField::new('sysConsent')->setLabel('entity.report.sys_consent'); + yield TextField::new('sysImpactAnalysis')->setLabel('entity.report.sys_impact_analysis'); + yield TextField::new('sysImpactAnalysisLink')->setLabel('entity.report.sys_impact_analysis_link'); + yield TextField::new('sysAuthorizationProcedure')->setLabel('entity.report.sys_authorization_procedure'); + yield TextField::new('sysVersion')->setLabel('entity.report.sys_version'); - if (Crud::PAGE_INDEX === $pageName) { - return [$title, $name, $systemOwner, $afdeling, $edocUrl, $text, $sys_link, $text, $groups]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$title, $internalId, $edocUrl, - $name, $text, $systemOwner, $groups, $answerarea, $alternativeTitle, $sys_updated, $owner, - $confidentialInformation, $purpose, $classification, $dateForRevision, $persons, $informationTypes, - $dataSentTo, $dataComeFrom, $dataLocation, $deletionDate, $dataWorthSaving, $dataProcessors, - $dataProcessingAgreement, $dataProcessingAgreementLink, $auditorStatement, $auditorStatementLink, - $dataToScience, $usage, $requestForInsight, $dateUse, $status, $remarks, $internalInformation, $obligationToInform, - $legalBasis, $consent, $impactAnalysis, $impactAnalysisLink, $authorizationProcedure, $version]; - } elseif (Crud::PAGE_EDIT === $pageName) { - return [$title2, $edocUrl, $groups, $text]; - } else { - throw new \Exception('Invalid page: '.$pageName); + return; + + case Crud::PAGE_NEW: + case Crud::PAGE_EDIT: + // Cf. https://github.com/itk-dev/sysstatus/blob/5383a3a566ce316c338441ed826ecf3fdcf98815/config/packages/easy_admin.yaml#L144-L150 + yield TextField::new('sysTitle')->setLabel('entity.report.sys_title') + ->setDisabled(); + yield TextEditorField::new('text'); + yield AssociationField::new('groups')->setLabel('entity.report.groups') + ->setPermission('ROLE_ADMIN'); + yield UrlField::new('eDocUrl')->setLabel('entity.report.edoc_url'); + + return; + + default: + throw new \Exception('Invalid page: '.$pageName); } } } diff --git a/src/Controller/Admin/SystemCrudController.php b/src/Controller/Admin/SystemCrudController.php index bf7a65aa..a30f9adb 100644 --- a/src/Controller/Admin/SystemCrudController.php +++ b/src/Controller/Admin/SystemCrudController.php @@ -5,10 +5,7 @@ use App\Entity\System; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; -use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; -use EasyCorp\Bundle\EasyAdminBundle\Config\Filters; -use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField; use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; @@ -17,25 +14,14 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\UrlField; -class SystemCrudController extends AbstractCrudController +class SystemCrudController extends AbstractFilterableCrudController { public static function getEntityFqcn(): string { return System::class; } - public function configureFilters(Filters $filters): Filters - { - $filters->add('name'); - - return parent::configureFilters($filters); // TODO: Change the autogenerated stub - } - - public function configureAssets(Assets $assets): Assets - { - return parent::configureAssets($assets)->addCssFile('styles.css'); - } - + #[\Override] public function configureActions(Actions $actions): Actions { $actions @@ -49,6 +35,7 @@ public function configureActions(Actions $actions): Actions /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { $id = IdField::new('id')->setLabel('entity.system.id'); diff --git a/src/Controller/Admin/ThemeCrudController.php b/src/Controller/Admin/ThemeCrudController.php index fb353ee3..2336087d 100644 --- a/src/Controller/Admin/ThemeCrudController.php +++ b/src/Controller/Admin/ThemeCrudController.php @@ -4,11 +4,12 @@ use App\Entity\Theme; use App\Form\ThemeCategoryType; +use EasyCorp\Bundle\EasyAdminBundle\Config\Action; +use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField; -use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; class ThemeCrudController extends AbstractCrudController @@ -18,39 +19,42 @@ public static function getEntityFqcn(): string return Theme::class; } + #[\Override] + public function configureCrud(Crud $crud): Crud + { + return parent::configureCrud($crud) + // https://symfony.com/bundles/EasyAdminBundle/current/design.html#form-field-templates + ->addFormTheme('admin/form.html.twig'); + } + + #[\Override] + public function configureActions(Actions $actions): Actions + { + return parent::configureActions($actions) + ->add(Crud::PAGE_INDEX, Action::DETAIL); + } + /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { - $id = IdField::new('id'); - $name = TextField::new('name'); - - $sysgroups = AssociationField::new('systemGroups') - ->setFormTypeOption('by_reference', false)->setLabel('Systemer') - ; - - $repgroups = AssociationField::new('reportGroups') - ->setFormTypeOption('by_reference', false)->setLabel('Anmeldelser') - ; - - $categoriesField = CollectionField::new('themeCategories')->setLabel('Tilføj Tema og Kategori') + yield TextField::new('name')->setLabel('entity.theme.name'); + // See templates/admin/form.html.twig for details on how we show this as a table. + yield CollectionField::new('themeCategories')->setLabel('entity.theme.categories') + ->setTemplatePath('admin/collection.html.twig') ->setEntryType(ThemeCategoryType::class) + ->renderExpanded() ->setFormTypeOptions([ 'by_reference' => false, // important for OneToMany associations ]) ; - - if (Crud::PAGE_INDEX === $pageName) { - return [$name, $sysgroups, $repgroups, $categoriesField]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$id]; - } elseif (Crud::PAGE_NEW === $pageName) { - return [$name, $sysgroups, $repgroups, $categoriesField]; - } elseif (Crud::PAGE_EDIT === $pageName) { - return [$name, $sysgroups, $repgroups, $categoriesField]; - } else { - throw new \Exception('Invalid page: '.$pageName); - } + yield AssociationField::new('systemGroups')->setLabel('entity.theme.system_groups') + ->setTemplatePath('admin/collection.html.twig') + ->setFormTypeOption('by_reference', false); + yield AssociationField::new('reportGroups')->setLabel('entity.theme.report_groups') + ->setTemplatePath('admin/collection.html.twig') + ->setFormTypeOption('by_reference', false); } } diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index eb35adb4..12579d91 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -7,7 +7,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; -use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField; use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; @@ -22,46 +21,29 @@ public static function getEntityFqcn(): string return User::class; } + #[\Override] public function configureActions(Actions $actions): Actions { - $actions - ->add(Crud::PAGE_INDEX, Action::DETAIL) - ->remove(Crud::PAGE_INDEX, Action::DELETE) - ->remove(Crud::PAGE_INDEX, Action::EDIT) - ; - - return $actions; + return parent::configureActions($actions) + ->add(Crud::PAGE_INDEX, Action::DETAIL); } /** * @throws \Exception */ + #[\Override] public function configureFields(string $pageName): iterable { - $username = TextField::new('username'); - $password = TextField::new('password'); - $email = EmailField::new('email'); - $groups = AssociationField::new('groups'); - $enabled = BooleanField::new('enabled'); - $lastLogin = DateTimeField::new('lastLogin'); - - $roles = ArrayField::new('roles'); - - $choice_roles = ChoiceField::new('roles')->setChoices([ + yield TextField::new('username'); + yield EmailField::new('email'); + yield AssociationField::new('groups') + ->hideOnIndex(); + yield BooleanField::new('enabled'); + yield DateTimeField::new('lastLogin') + ->hideOnForm(); + yield ChoiceField::new('roles')->setChoices([ 'User' => 'ROLE_USER', 'Admin' => 'ROLE_ADMIN', - ])->allowMultipleChoices(true)->renderExpanded()->setEmptyData(false); - - if (Crud::PAGE_INDEX === $pageName) { - return [$username, $email, $enabled, $lastLogin, $roles]; - } elseif (Crud::PAGE_DETAIL === $pageName) { - return [$username, $email, $groups, $enabled, $lastLogin, $roles]; - } elseif (Crud::PAGE_NEW === $pageName) { - return [$username, $email, $groups, $enabled, $password, $choice_roles]; - } elseif (Crud::PAGE_EDIT === $pageName) { - return [$username, $email, $groups, $enabled, $password, $choice_roles]; - } else { - throw new \Exception('Invalid page: '.$pageName); - } + ])->allowMultipleChoices()->renderExpanded()->setEmptyData(false); } } diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php new file mode 100644 index 00000000..5181ebcf --- /dev/null +++ b/src/Controller/DefaultController.php @@ -0,0 +1,16 @@ +redirectToRoute('admin'); + } +} diff --git a/src/Controller/ExportController.php b/src/Controller/ExportController.php index 39664163..4d3a5f0e 100644 --- a/src/Controller/ExportController.php +++ b/src/Controller/ExportController.php @@ -10,7 +10,7 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; /** * Class ExportController. @@ -18,35 +18,30 @@ class ExportController extends AbstractController { /** - * @Route("/export/report", name="export_report") - * * @throws Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ - public function exportReports( - DataExporter $dataExporter, - ) { + #[Route(path: '/export/report', name: 'export_report')] + public function exportReports(DataExporter $dataExporter): void + { $dataExporter->exportReport(); } /** - * @Route("/export/system", name="export_system") - * * @throws Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ - public function exportSystems( - DataExporter $dataExporter, - ) { + #[Route(path: '/export/system', name: 'export_system')] + public function exportSystems(DataExporter $dataExporter): void + { $dataExporter->exportSystem(); } /** - * @Route("/export", name="export_page") - * * @throws Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ + #[Route(path: '/export', name: 'export_page')] public function exportPage(Request $request, DataExporter $dataExporter, GroupRepository $groupRepository): Response { $groups = $groupRepository->findAll(); diff --git a/src/Controller/LoginController.php b/src/Controller/LoginController.php index 25d234bf..94f4015c 100644 --- a/src/Controller/LoginController.php +++ b/src/Controller/LoginController.php @@ -3,30 +3,31 @@ namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; class LoginController extends AbstractController { - #[Route('/', name: 'app_login')] - // public function index(): Response + #[Route(path: '/login', name: 'app_login')] public function index(AuthenticationUtils $authenticationUtils): Response { - // get the login error if there is one + // Get the login error if there is one. $error = $authenticationUtils->getLastAuthenticationError(); - // last username entered by the user + // Last username entered by the user. $lastUsername = $authenticationUtils->getLastUsername(); return $this->render('login/index.html.twig', [ 'last_username' => $lastUsername, 'error' => $error, + 'target_path' => $this->generateUrl('admin'), ]); } #[Route(path: '/logout', name: 'admin_logout')] - public function logout() + public function logout(): RedirectResponse { return $this->redirectToRoute('app_login'); } diff --git a/src/DBAL/Types/SmileyType.php b/src/DBAL/Types/SmileyType.php index 72eee8ce..d1e9c64a 100644 --- a/src/DBAL/Types/SmileyType.php +++ b/src/DBAL/Types/SmileyType.php @@ -9,10 +9,10 @@ */ final class SmileyType extends AbstractEnumType { - public const GREEN = 'GREEN'; - public const RED = 'RED'; - public const BLUE = 'BLUE'; - public const YELLOW = 'YELLOW'; + public const string GREEN = 'GREEN'; + public const string RED = 'RED'; + public const string BLUE = 'BLUE'; + public const string YELLOW = 'YELLOW'; protected static array $choices = [ self::GREEN => 'Green', diff --git a/src/Doctrine/EntityActiveFilter.php b/src/Doctrine/EntityActiveFilter.php new file mode 100644 index 00000000..d304c876 --- /dev/null +++ b/src/Doctrine/EntityActiveFilter.php @@ -0,0 +1,31 @@ +getName()) { + case Report::class: + return sprintf( + '(%1$s.archived_at IS NULL AND %1$s.sys_status = %2$s)', + $targetTableAlias, + $this->getConnection()->quote(Report::STATUS_ACTIVE) + ); + case System::class: + return sprintf( + '(%1$s.archived_at IS NULL AND %1$s.sys_status <> %2$s)', + $targetTableAlias, + $this->getConnection()->quote(System::STATUS_NOT_ACTIVE) + ); + } + + return ''; + } +} diff --git a/src/Entity/Answer.php b/src/Entity/Answer.php index b9c28596..883eefb1 100644 --- a/src/Entity/Answer.php +++ b/src/Entity/Answer.php @@ -13,19 +13,19 @@ #[ORM\Entity(repositoryClass: AnswerRepository::class)] #[\Gedmo\Mapping\Annotation\Loggable] -class Answer +class Answer implements \Stringable { use BlameableEntity; use TimestampableEntity; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; #[ORM\ManyToOne(inversedBy: 'answers')] #[ORM\JoinColumn(nullable: false)] - private ?Question $question = null; + private Question $question; #[ORM\Column(type: Types::TEXT, nullable: true)] #[Versioned] @@ -42,7 +42,7 @@ class Answer #[ORM\ManyToOne(inversedBy: 'answers')] private ?Report $report = null; - public function __toString() + public function __toString(): string { return $this->getNote() ?? ''; } diff --git a/src/Entity/Category.php b/src/Entity/Category.php index 35c7dd8e..c4fbdb10 100644 --- a/src/Entity/Category.php +++ b/src/Entity/Category.php @@ -15,23 +15,29 @@ #[ORM\Entity(repositoryClass: CategoryRepository::class)] #[Loggable] #[UniqueEntity('name')] -class Category +class Category implements \Stringable { use BlameableEntity; use TimestampableEntity; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; - #[ORM\Column(length: 255, unique: true)] + #[ORM\Column(length: 255, unique: true, nullable: true)] #[Versioned] private ?string $name = null; + /** + * @var Collection + */ #[ORM\OneToMany(mappedBy: 'category', targetEntity: ThemeCategory::class, orphanRemoval: true)] private Collection $themeCategories; + /** + * @var Collection + */ #[ORM\OneToMany(mappedBy: 'category', targetEntity: Question::class, cascade: ['persist'])] private Collection $questions; @@ -41,9 +47,9 @@ public function __construct() $this->questions = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->getName() ?: $this->getId(); + return (string) ($this->getName() ?: $this->getId()); } public function getId(): ?int @@ -83,13 +89,17 @@ public function removeThemeCategory(ThemeCategory $themeCategory): self /** * Virtual. + * + * @return array + * + * @throws \Exception */ - public function getThemes() + public function getThemes(): array { $list = []; $iterator = $this->themeCategories->getIterator(); - foreach ($iterator as $i => $item) { + foreach ($iterator as $item) { $list[$item->getTheme()->getId()] = $item->getTheme(); } diff --git a/src/Entity/ImportRun.php b/src/Entity/ImportRun.php index 8c116036..efee43b8 100644 --- a/src/Entity/ImportRun.php +++ b/src/Entity/ImportRun.php @@ -11,19 +11,19 @@ class ImportRun { #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $datetime = null; - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?bool $result = null; #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $output = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $type = null; public function getId(): ?int diff --git a/src/Entity/Question.php b/src/Entity/Question.php index e637616d..974a6ccb 100644 --- a/src/Entity/Question.php +++ b/src/Entity/Question.php @@ -14,27 +14,30 @@ #[ORM\Entity(repositoryClass: QuestionRepository::class)] #[Loggable] -class Question +class Question implements \Stringable { use BlameableEntity; use TimestampableEntity; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; #[ORM\ManyToOne(inversedBy: 'questions')] private ?Category $category = null; - #[ORM\Column(type: Types::TEXT)] + #[ORM\Column(type: Types::TEXT, nullable: true)] #[Versioned] private ?string $question = null; - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $sortOrder = null; - #[ORM\OneToMany(mappedBy: 'question', targetEntity: Answer::class, orphanRemoval: 'true')] + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'question', targetEntity: Answer::class, orphanRemoval: true)] private Collection $answers; public function __construct() @@ -42,9 +45,9 @@ public function __construct() $this->answers = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->getQuestion() ?: $this->getId(); + return (string) ($this->getQuestion() ?: $this->getId()); } public function getId(): ?int @@ -76,17 +79,11 @@ public function setQuestion(string $question): self return $this; } - /** - * @return mixed - */ public function getSortOrder(): ?int { return $this->sortOrder; } - /** - * @param mixed $sortOrder - */ public function setSortOrder(int $sortOrder): self { $this->sortOrder = $sortOrder; diff --git a/src/Entity/Report.php b/src/Entity/Report.php index 27396f96..5523f0d5 100644 --- a/src/Entity/Report.php +++ b/src/Entity/Report.php @@ -15,21 +15,25 @@ #[ORM\Entity(repositoryClass: ReportRepository::class)] #[Loggable] -class Report +class Report implements \Stringable { use BlameableEntity; use TimestampableEntity; use ArchivableEntity; + public const string STATUS_ACTIVE = 'Aktiv'; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; + /** + * @var Collection + */ #[ORM\OneToMany(mappedBy: 'report', targetEntity: Answer::class)] private Collection $answers; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] #[Versioned] private ?string $name = null; @@ -37,7 +41,7 @@ class Report #[Versioned] private ?string $text = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] #[Versioned] private ?string $sysSystemOwner = null; @@ -134,7 +138,7 @@ class Report #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $sysInternalInformation = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $sysLink = null; #[ORM\Column(nullable: true)] @@ -155,10 +159,13 @@ class Report #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $sysImpactAnalysisLink = null; - #[ORM\Column(length: 255, nullable: true, name: 'edoc_url')] + #[ORM\Column(name: 'edoc_url', length: 255, nullable: true)] private ?string $eDocUrl = null; - #[ORM\ManyToMany(targetEntity: Group::class, inversedBy: 'reports')] + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: UserGroup::class, inversedBy: 'reports')] private Collection $groups; public function __construct() @@ -167,9 +174,9 @@ public function __construct() $this->groups = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->getName(); + return (string) $this->getName(); } public function getId(): ?int @@ -222,7 +229,7 @@ public function setName(string $name): self /** * Virtual property. */ - public function getTextSet() + public function getTextSet(): bool { return isset($this->text); } @@ -602,9 +609,9 @@ public function setSysVersion(?string $sysVersion): self /** * Virtual property. */ - public function getShowableName() + public function getShowableName(): ?string { - return isset($this->sysTitle) ? $this->sysTitle : $this->getName(); + return $this->sysTitle ?? $this->getName(); } public function getSysOwnerSub(): ?string @@ -621,8 +628,10 @@ public function setSysOwnerSub(?string $sysOwnerSub): self /** * Virtual property. + * + * @return array */ - public function getAnswerArea() + public function getAnswerArea(): array { $themes = []; $groups = $this->getGroups(); @@ -743,14 +752,14 @@ public function setEDocUrl(?string $eDocUrl): self } /** - * @return Collection + * @return Collection */ public function getGroups(): Collection { return $this->groups; } - public function addGroup(Group $group): self + public function addGroup(UserGroup $group): self { if (!$this->groups->contains($group)) { $this->groups->add($group); @@ -759,7 +768,7 @@ public function addGroup(Group $group): self return $this; } - public function removeGroup(Group $group): self + public function removeGroup(UserGroup $group): self { $this->groups->removeElement($group); diff --git a/src/Entity/SelfServiceAvailableFromItem.php b/src/Entity/SelfServiceAvailableFromItem.php index 7d3bc263..2a9f8679 100644 --- a/src/Entity/SelfServiceAvailableFromItem.php +++ b/src/Entity/SelfServiceAvailableFromItem.php @@ -9,18 +9,21 @@ use Gedmo\Timestampable\Traits\TimestampableEntity; #[ORM\Entity(repositoryClass: SelfServiceAvailableFromItemRepository::class)] -class SelfServiceAvailableFromItem +class SelfServiceAvailableFromItem implements \Stringable { use TimestampableEntity; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $name = null; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: System::class, inversedBy: 'selfServiceAvailableFromItems')] private Collection $systems; @@ -29,9 +32,9 @@ public function __construct() $this->systems = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->name ?? __CLASS__; + return $this->name ?? self::class; } public function getId(): ?int diff --git a/src/Entity/System.php b/src/Entity/System.php index 7197fb6c..1ae13d3b 100644 --- a/src/Entity/System.php +++ b/src/Entity/System.php @@ -15,24 +15,31 @@ #[ORM\Entity(repositoryClass: SystemRepository::class)] #[Loggable] -class System +class System implements \Stringable { use BlameableEntity; use TimestampableEntity; use ArchivableEntity; + public const string STATUS_NOT_ACTIVE = 'Systemet bruges ikke længere'; #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: SelfServiceAvailableFromItem::class, mappedBy: 'systems')] private Collection $selfServiceAvailableFromItems; + /** + * @var Collection + */ #[ORM\OneToMany(mappedBy: 'system', targetEntity: Answer::class)] private Collection $answers; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] #[Versioned] private ?string $name = null; @@ -40,7 +47,7 @@ class System #[Versioned] private ?string $text = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] #[Versioned] private ?string $sysSystemOwner = null; @@ -119,7 +126,7 @@ class System #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $sysOwnerSub = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $sysLink = null; #[ORM\Column(nullable: true)] @@ -131,7 +138,10 @@ class System #[ORM\Column(name: 'edoc_url', length: 255, nullable: true)] private ?string $eDocUrl = null; - #[ORM\ManyToMany(targetEntity: Group::class, inversedBy: 'systems')] + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: UserGroup::class, inversedBy: 'systems')] private Collection $groups; #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] @@ -153,9 +163,9 @@ public function __construct() $this->groups = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->getName(); + return (string) $this->getName(); } public function getId(): ?int @@ -605,14 +615,14 @@ public function setEDocUrl(?string $eDocUrl): self } /** - * @return Collection + * @return Collection */ public function getGroups(): Collection { return $this->groups; } - public function addGroup(Group $group): self + public function addGroup(UserGroup $group): self { if (!$this->groups->contains($group)) { $this->groups->add($group); @@ -621,7 +631,7 @@ public function addGroup(Group $group): self return $this; } - public function removeGroup(Group $group): self + public function removeGroup(UserGroup $group): self { $this->groups->removeElement($group); @@ -667,7 +677,7 @@ public function setSysOpenData(?string $sysOpenData): self /** * Virtual property. */ - public function getSysIdAsLink() + public function getSysIdAsLink(): ?string { return $this->getSysId(); } @@ -675,23 +685,25 @@ public function getSysIdAsLink() /** * Virtual property. */ - public function getShowableName() + public function getShowableName(): ?string { - return isset($this->sysTitle) ? $this->sysTitle : $this->getName(); + return $this->sysTitle ?? $this->getName(); } /** * Virtual property. */ - public function getTextSet() + public function getTextSet(): bool { return isset($this->text); } /** * Virtual property. + * + * @return array */ - public function getAnswerArea() + public function getAnswerArea(): array { $themes = []; $groups = $this->getGroups(); @@ -703,9 +715,11 @@ public function getAnswerArea() return $themes; } - public function setSysNumberOfUsers($sysNumberOfUsers) + public function setSysNumberOfUsers(string $sysNumberOfUsers): self { $this->sysNumberOfUsers = $sysNumberOfUsers; + + return $this; } public function getSysNumberOfUsers(): ?string diff --git a/src/Entity/Theme.php b/src/Entity/Theme.php index 1d4c1cdd..b48422d4 100644 --- a/src/Entity/Theme.php +++ b/src/Entity/Theme.php @@ -5,6 +5,7 @@ use App\Repository\ThemeRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping as ORM; use Gedmo\Blameable\Traits\BlameableEntity; use Gedmo\Mapping\Annotation\Loggable; @@ -15,7 +16,7 @@ #[ORM\Entity(repositoryClass: ThemeRepository::class)] #[Loggable] #[UniqueEntity('name')] -class Theme +class Theme implements \Stringable { use BlameableEntity; use TimestampableEntity; @@ -25,35 +26,39 @@ class Theme #[ORM\Column] private ?int $id = null; + /** + * @var Collection + */ #[ORM\OneToMany(mappedBy: 'theme', targetEntity: ThemeCategory::class, cascade: ['persist'], orphanRemoval: true)] + #[ORM\OrderBy(['sortOrder' => Criteria::ASC])] private Collection $themeCategories; /** - * @var ArrayCollection + * @var Collection */ - private $categories; - - #[ORM\ManyToMany(targetEntity: Group::class, mappedBy: 'systemThemes')] + #[ORM\ManyToMany(targetEntity: UserGroup::class, mappedBy: 'systemThemes')] private Collection $systemGroups; - #[ORM\ManyToMany(targetEntity: Group::class, mappedBy: 'reportThemes')] + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: UserGroup::class, mappedBy: 'reportThemes')] private Collection $reportGroups; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] #[Versioned] private ?string $name = null; public function __construct() { - $this->categories = new ArrayCollection(); $this->themeCategories = new ArrayCollection(); $this->systemGroups = new ArrayCollection(); $this->reportGroups = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->getName() ?: $this->getId(); + return (string) ($this->getName() ?: $this->getId()); } public function getId(): ?int @@ -93,6 +98,10 @@ public function removeThemeCategory(ThemeCategory $themeCategory): self /** * Virtual. + * + * @return array + * + * @throws \Exception */ public function getOrderedCategories(): array { @@ -100,11 +109,10 @@ public function getOrderedCategories(): array $themeCategories = $this->themeCategories; $iterator = $themeCategories->getIterator(); - $iterator->uasort(function ($first, $second) { - return (int) $first->getSortOrder() < (int) $second->getSortOrder() ? 1 : -1; - }); + $iterator->uasort(static fn ($first, $second) => (int) $first->getSortOrder() <=> (int) $second->getSortOrder()); - foreach ($iterator as $i => $item) { + /** @var ThemeCategory $item */ + foreach ($iterator as $item) { $list[] = $item->getCategory(); } @@ -112,14 +120,14 @@ public function getOrderedCategories(): array } /** - * @return Collection + * @return Collection */ public function getSystemGroups(): Collection { return $this->systemGroups; } - public function addSystemGroup(Group $systemGroup): self + public function addSystemGroup(UserGroup $systemGroup): self { if (!$this->systemGroups->contains($systemGroup)) { $this->systemGroups->add($systemGroup); @@ -129,7 +137,7 @@ public function addSystemGroup(Group $systemGroup): self return $this; } - public function removeSystemGroup(Group $systemGroup): self + public function removeSystemGroup(UserGroup $systemGroup): self { if ($this->systemGroups->removeElement($systemGroup)) { $systemGroup->removeSystemTheme($this); @@ -139,14 +147,14 @@ public function removeSystemGroup(Group $systemGroup): self } /** - * @return Collection + * @return Collection */ public function getReportGroups(): Collection { return $this->reportGroups; } - public function addReportGroup(Group $reportGroup): self + public function addReportGroup(UserGroup $reportGroup): self { if (!$this->reportGroups->contains($reportGroup)) { $this->reportGroups->add($reportGroup); @@ -156,10 +164,10 @@ public function addReportGroup(Group $reportGroup): self return $this; } - public function removeReportGroup(Group $reportGroup): self + public function removeReportGroup(UserGroup $reportGroup): self { if ($this->reportGroups->removeElement($reportGroup)) { - $reportGroup->removeSystemTheme($this); + $reportGroup->removeReportTheme($this); } return $this; diff --git a/src/Entity/ThemeCategory.php b/src/Entity/ThemeCategory.php index 7b2e4895..7980c35a 100644 --- a/src/Entity/ThemeCategory.php +++ b/src/Entity/ThemeCategory.php @@ -8,7 +8,7 @@ use Gedmo\Timestampable\Traits\TimestampableEntity; #[ORM\Entity(repositoryClass: ThemeCategoryRepository::class)] -class ThemeCategory +class ThemeCategory implements \Stringable { use BlameableEntity; use TimestampableEntity; @@ -18,16 +18,21 @@ class ThemeCategory private ?int $id = null; #[ORM\ManyToOne(inversedBy: 'themeCategories')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: true)] private ?Theme $theme = null; #[ORM\ManyToOne(inversedBy: 'themeCategories')] #[ORM\JoinColumn(nullable: false)] - private ?Category $category = null; + private Category $category; - #[ORM\Column(type: 'integer', options: ['default' => 0])] + #[ORM\Column(type: 'integer', nullable: true, options: ['default' => 0])] private ?int $sortOrder = 0; + public function __toString(): string + { + return sprintf('%d: %s', $this->sortOrder, $this->getCategory()?->getName()); + } + public function getId(): ?int { return $this->id; diff --git a/src/Entity/User.php b/src/Entity/User.php index a494528c..a9dca53f 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -13,9 +13,9 @@ use Symfony\Component\Security\Core\User\UserInterface; #[ORM\Entity(repositoryClass: UserRepository::class)] -#[ORM\Table(name: 'fos_user')] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])] -class User implements UserInterface, PasswordAuthenticatedUserInterface +#[ORM\UniqueConstraint(fields: ['email'])] +class User implements UserInterface, PasswordAuthenticatedUserInterface, \Stringable { use BlameableEntity; use TimestampableEntity; @@ -25,25 +25,30 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column] private ?int $id = null; - #[ORM\ManyToMany(targetEntity: Group::class, inversedBy: 'users')] - #[ORM\JoinTable(name: 'fos_user_user_group')] + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: UserGroup::class, inversedBy: 'users')] private Collection $groups; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $username = null; - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?string $password = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $email = null; #[ORM\Column] - private ?bool $enabled = null; + private bool $enabled = false; #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $lastLogin = null; + /** + * @var array + */ #[ORM\Column] private array $roles = []; @@ -52,25 +57,35 @@ public function __construct() $this->groups = new ArrayCollection(); } + public function __toString(): string + { + return (string) $this->username; + } + public function getId(): ?int { return $this->id; } /** - * @return Collection + * @return Collection */ public function getGroups(): Collection { return $this->groups; } - public function setGroups(Collection $groups): void + /** + * @param Collection $groups + */ + public function setGroups(Collection $groups): self { $this->groups = $groups; + + return $this; } - public function addGroup(Group $group): self + public function addGroup(UserGroup $group): self { if (!$this->groups->contains($group)) { $this->groups->add($group); @@ -79,7 +94,7 @@ public function addGroup(Group $group): self return $this; } - public function removeGroup(Group $group): self + public function removeGroup(UserGroup $group): self { $this->groups->removeElement($group); @@ -120,7 +135,7 @@ public function setEmail(string $email): self return $this; } - public function isEnabled(): ?bool + public function isEnabled(): bool { return $this->enabled; } diff --git a/src/Entity/Group.php b/src/Entity/UserGroup.php similarity index 84% rename from src/Entity/Group.php rename to src/Entity/UserGroup.php index 6270efe2..5b7d0f46 100644 --- a/src/Entity/Group.php +++ b/src/Entity/UserGroup.php @@ -4,39 +4,60 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Order; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -// #[ORM\Entity(repositoryClass: GroupRepository::class)] #[ORM\Entity] -#[ORM\Table(name: 'fos_group')] -class Group +class UserGroup implements \Stringable { #[ORM\Id] #[ORM\GeneratedValue] - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?int $id = null; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: Theme::class, inversedBy: 'systemGroups')] #[ORM\JoinTable(name: 'group_system_themes')] + #[ORM\OrderBy(['name' => Order::Ascending->value])] private Collection $systemThemes; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: Theme::class, inversedBy: 'reportGroups')] #[ORM\JoinTable(name: 'group_report_themes')] + #[ORM\OrderBy(['name' => Order::Ascending->value])] private Collection $reportThemes; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: Report::class, mappedBy: 'groups')] + #[ORM\OrderBy(['name' => Order::Ascending->value])] private Collection $reports; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: System::class, mappedBy: 'groups')] + #[ORM\OrderBy(['name' => Order::Ascending->value])] private Collection $systems; + /** + * @var Collection + */ #[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'groups')] private Collection $users; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $name = null; + /** + * @var array + */ #[ORM\Column(type: Types::JSON)] private array $roles = []; @@ -49,9 +70,9 @@ public function __construct() $this->users = new ArrayCollection(); } - public function __toString() + public function __toString(): string { - return $this->name; + return (string) $this->name; } public function getId(): ?int @@ -206,11 +227,19 @@ public function setName(string $name): self return $this; } + /** + * @return string[] + */ public function getRoles(): array { return $this->roles; } + /** + * @param array $roles + * + * @return $this + */ public function setRoles(array $roles): self { $this->roles = $roles; diff --git a/src/Form/ThemeCategoryType.php b/src/Form/ThemeCategoryType.php index 07004ce8..91f9f9b5 100644 --- a/src/Form/ThemeCategoryType.php +++ b/src/Form/ThemeCategoryType.php @@ -10,11 +10,8 @@ class ThemeCategoryType extends AbstractType { - private ThemeManager $themeManager; - - public function __construct(ThemeManager $themeManager) + public function __construct(private readonly ThemeManager $themeManager) { - $this->themeManager = $themeManager; } public function buildForm(FormBuilderInterface $builder, array $options): void diff --git a/src/Repository/AnswerRepository.php b/src/Repository/AnswerRepository.php index 26529bcf..7c6e0a01 100644 --- a/src/Repository/AnswerRepository.php +++ b/src/Repository/AnswerRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method Answer|null find($id, $lockMode = null, $lockVersion = null) - * @method Answer|null findOneBy(array $criteria, array $orderBy = null) - * @method Answer[] findAll() - * @method Answer[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class AnswerRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(Answer $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return Answer[] Returns an array of Answer objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('a') - // ->andWhere('a.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('a.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Answer - // { - // return $this->createQueryBuilder('a') - // ->andWhere('a.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/CategoryRepository.php b/src/Repository/CategoryRepository.php index b219b56b..d9623d1e 100644 --- a/src/Repository/CategoryRepository.php +++ b/src/Repository/CategoryRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method Category|null find($id, $lockMode = null, $lockVersion = null) - * @method Category|null findOneBy(array $criteria, array $orderBy = null) - * @method Category[] findAll() - * @method Category[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class CategoryRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(Category $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return Category[] Returns an array of Category objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('c') - // ->andWhere('c.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('c.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Category - // { - // return $this->createQueryBuilder('c') - // ->andWhere('c.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/GroupRepository.php b/src/Repository/GroupRepository.php index 9bd10556..b06eb97d 100644 --- a/src/Repository/GroupRepository.php +++ b/src/Repository/GroupRepository.php @@ -2,26 +2,22 @@ namespace App\Repository; -use App\Entity\Group; +use App\Entity\User; +use App\Entity\UserGroup; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; /** - * @extends ServiceEntityRepository - * - * @method Group|null find($id, $lockMode = null, $lockVersion = null) - * @method Group|null findOneBy(array $criteria, array $orderBy = null) - * @method Group[] findAll() - * @method Group[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @extends ServiceEntityRepository */ class GroupRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { - parent::__construct($registry, Group::class); + parent::__construct($registry, UserGroup::class); } - public function save(Group $entity, bool $flush = false): void + public function save(UserGroup $entity, bool $flush = false): void { $this->getEntityManager()->persist($entity); @@ -30,7 +26,7 @@ public function save(Group $entity, bool $flush = false): void } } - public function remove(Group $entity, bool $flush = false): void + public function remove(UserGroup $entity, bool $flush = false): void { $this->getEntityManager()->remove($entity); @@ -40,9 +36,9 @@ public function remove(Group $entity, bool $flush = false): void } /** - * @return Group[] Returns an array of Group objects + * @return UserGroup[] Returns an array of Group objects */ - public function findByUser($user): array + public function findByUser(User $user): array { return $this->createQueryBuilder('g') ->andWhere(':val MEMBER OF g.users') @@ -51,14 +47,4 @@ public function findByUser($user): array ->getResult() ; } - - // public function findOneBySomeField($value): ?Group - // { - // return $this->createQueryBuilder('g') - // ->andWhere('g.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/ImportRunRepository.php b/src/Repository/ImportRunRepository.php index e012ac89..56de4029 100644 --- a/src/Repository/ImportRunRepository.php +++ b/src/Repository/ImportRunRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method ImportRun|null find($id, $lockMode = null, $lockVersion = null) - * @method ImportRun|null findOneBy(array $criteria, array $orderBy = null) - * @method ImportRun[] findAll() - * @method ImportRun[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ImportRunRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(ImportRun $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return ImportRun[] Returns an array of ImportRun objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('i') - // ->andWhere('i.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('i.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?ImportRun - // { - // return $this->createQueryBuilder('i') - // ->andWhere('i.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/QuestionRepository.php b/src/Repository/QuestionRepository.php index a11848cf..fb5802ef 100644 --- a/src/Repository/QuestionRepository.php +++ b/src/Repository/QuestionRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method Question|null find($id, $lockMode = null, $lockVersion = null) - * @method Question|null findOneBy(array $criteria, array $orderBy = null) - * @method Question[] findAll() - * @method Question[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class QuestionRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(Question $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return Question[] Returns an array of Question objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('q') - // ->andWhere('q.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('q.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Question - // { - // return $this->createQueryBuilder('q') - // ->andWhere('q.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/ReportRepository.php b/src/Repository/ReportRepository.php index 5fc16d95..d360fcc2 100644 --- a/src/Repository/ReportRepository.php +++ b/src/Repository/ReportRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method Report|null find($id, $lockMode = null, $lockVersion = null) - * @method Report|null findOneBy(array $criteria, array $orderBy = null) - * @method Report[] findAll() - * @method Report[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ReportRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(Report $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return Report[] Returns an array of Report objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('r') - // ->andWhere('r.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('r.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Report - // { - // return $this->createQueryBuilder('r') - // ->andWhere('r.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/SelfServiceAvailableFromItemRepository.php b/src/Repository/SelfServiceAvailableFromItemRepository.php index 9bd1f2c9..e53d0df0 100644 --- a/src/Repository/SelfServiceAvailableFromItemRepository.php +++ b/src/Repository/SelfServiceAvailableFromItemRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method SelfServiceAvailableFromItem|null find($id, $lockMode = null, $lockVersion = null) - * @method SelfServiceAvailableFromItem|null findOneBy(array $criteria, array $orderBy = null) - * @method SelfServiceAvailableFromItem[] findAll() - * @method SelfServiceAvailableFromItem[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class SelfServiceAvailableFromItemRepository extends ServiceEntityRepository { @@ -44,7 +39,7 @@ public function remove(SelfServiceAvailableFromItem $entity, bool $flush = false * * @return SelfServiceAvailableFromItem */ - public function getItem(string $name) + public function getItem(string $name): SelfServiceAvailableFromItem { $item = $this->findOneBy(['name' => $name]); @@ -62,29 +57,4 @@ public function getItem(string $name) return $item; } - - // /** - // * @return SelfServiceAvailableFromItem[] Returns an array of SelfServiceAvailableFromItem objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('s.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?SelfServiceAvailableFromItem - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/SystemRepository.php b/src/Repository/SystemRepository.php index c95959e3..4f08c464 100644 --- a/src/Repository/SystemRepository.php +++ b/src/Repository/SystemRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method System|null find($id, $lockMode = null, $lockVersion = null) - * @method System|null findOneBy(array $criteria, array $orderBy = null) - * @method System[] findAll() - * @method System[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class SystemRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(System $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return System[] Returns an array of System objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('s.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?System - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/TestUserRepository.php b/src/Repository/TestUserRepository.php deleted file mode 100644 index 2a7002d4..00000000 --- a/src/Repository/TestUserRepository.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -class TestUserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TestUser::class); - } - - /** - * Used to upgrade (rehash) the user's password automatically over time. - */ - public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void - { - if (!$user instanceof TestUser) { - throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class)); - } - - $user->setPassword($newHashedPassword); - $this->getEntityManager()->persist($user); - $this->getEntityManager()->flush(); - } - - // /** - // * @return TestUser[] Returns an array of TestUser objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('t.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?TestUser - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } -} diff --git a/src/Repository/ThemeCategoryRepository.php b/src/Repository/ThemeCategoryRepository.php index 805df5eb..399394be 100644 --- a/src/Repository/ThemeCategoryRepository.php +++ b/src/Repository/ThemeCategoryRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method ThemeCategory|null find($id, $lockMode = null, $lockVersion = null) - * @method ThemeCategory|null findOneBy(array $criteria, array $orderBy = null) - * @method ThemeCategory[] findAll() - * @method ThemeCategory[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ThemeCategoryRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(ThemeCategory $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return ThemeCategory[] Returns an array of ThemeCategory objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('t.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?ThemeCategory - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/ThemeRepository.php b/src/Repository/ThemeRepository.php index 8640992c..752f5da1 100644 --- a/src/Repository/ThemeRepository.php +++ b/src/Repository/ThemeRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method Theme|null find($id, $lockMode = null, $lockVersion = null) - * @method Theme|null findOneBy(array $criteria, array $orderBy = null) - * @method Theme[] findAll() - * @method Theme[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ThemeRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(Theme $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return Theme[] Returns an array of Theme objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('t.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Theme - // { - // return $this->createQueryBuilder('t') - // ->andWhere('t.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 838478d8..583d25d4 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -8,11 +8,6 @@ /** * @extends ServiceEntityRepository - * - * @method User|null find($id, $lockMode = null, $lockVersion = null) - * @method User|null findOneBy(array $criteria, array $orderBy = null) - * @method User[] findAll() - * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class UserRepository extends ServiceEntityRepository { @@ -38,29 +33,4 @@ public function remove(User $entity, bool $flush = false): void $this->getEntityManager()->flush(); } } - - // /** - // * @return User[] Returns an array of User objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('u') - // ->andWhere('u.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('u.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?User - // { - // return $this->createQueryBuilder('u') - // ->andWhere('u.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/src/Service/BaseImporter.php b/src/Service/BaseImporter.php index a86424cd..9dc9ad12 100644 --- a/src/Service/BaseImporter.php +++ b/src/Service/BaseImporter.php @@ -9,32 +9,23 @@ abstract class BaseImporter implements ImportInterface { - protected EntityManagerInterface $entityManager; - protected ReportRepository $reportRepository; - protected SystemRepository $systemRepository; - protected GroupRepository $groupRepository; - protected string|array|false $url; + protected string $url; public function __construct( - ReportRepository $reportRepository, - SystemRepository $systemRepository, - GroupRepository $groupRepository, - EntityManagerInterface $entityManager, + protected ReportRepository $reportRepository, + protected SystemRepository $systemRepository, + protected GroupRepository $groupRepository, + protected EntityManagerInterface $entityManager, ) { - $this->reportRepository = $reportRepository; - $this->systemRepository = $systemRepository; - $this->groupRepository = $groupRepository; - $this->entityManager = $entityManager; - $this->url = getenv('SYSTEM_URL'); } - protected function sanitizeText(string $str) + protected function sanitizeText(string $str): ?string { $str = strip_tags($str, '